Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

104
Src/Wasabi/bfc/assert.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "precomp_wasabi_bfc.h"
#ifdef WIN32
#include <windows.h>
#endif
#ifdef __APPLE__
#include <unistd.h>
#endif
#include "bfc_assert.h"
#ifdef ASSERTS_ENABLED
static int in_assert = 0;
// we try to use wsprintf because it can make for a smaller .exe
#ifdef WIN32
#define ASSERT_SPRINTF wsprintfA
#elif defined(LINUX)
#define ASSERT_SPRINTF sprintf
#elif defined(__APPLE__)
#define ASSERT_SPRINTF sprintf
#else
#error port me!
#endif
#ifdef WIN32
static int isDebuggerPresent() {
HINSTANCE kernel32 = LoadLibrary(L"kernel32.dll");
if (kernel32 == NULL) return 0;
BOOL (WINAPI *IsDebuggerPresent)() = NULL;
IsDebuggerPresent = (BOOL (WINAPI *)())GetProcAddress(kernel32, "IsDebuggerPresent");
if (IsDebuggerPresent == NULL) return 0;
int ret = (*IsDebuggerPresent)();
FreeLibrary(kernel32);
return ret;
}
#endif
static void assert_kill()
{
#ifdef _WIN32
#ifndef _WIN64
__asm { int 3 };
#else
ExitProcess(0);
#endif
#endif
}
void _assert_handler(const char *reason, const char *file, int line) {
char msg[4096] = {0};
ASSERT_SPRINTF(msg, "Expression: %s\nFile: %s\nLine: %d\n", reason, file, line);
#ifdef WIN32
OutputDebugStringA(msg);
if (in_assert)
{
assert_kill();
}
in_assert = 1;
ATOM a = AddAtom(L"BYPASS_DEACTIVATE_MGR"); // so we don't need to call api->appdeactivation_setbypass
if (isDebuggerPresent() || MessageBoxA(NULL, msg, "Assertion failed", MB_OKCANCEL|MB_TASKMODAL) == IDCANCEL) {
assert_kill();
} else
ExitProcess(0);
DeleteAtom(a);
#elif defined(LINUX)
kill(getpid(), SIGSEGV );
#elif defined(__APPLE__)
kill(getpid(), SIGSEGV );
#else
#error port me!
#endif
in_assert = 0;
}
void _assert_handler_str(const char *string, const char *reason, const char *file, int line)
{
char msg[4096] = {0};
ASSERT_SPRINTF(msg, "\"%s\"\nExpression: %s\nFile: %s\nLine: %d\n", string, reason ? reason : "", file, line);
#ifdef WIN32
OutputDebugStringA(msg);
if (in_assert) assert_kill();
in_assert = 1;
ATOM a = AddAtom(L"BYPASS_DEACTIVATE_MGR");
if (isDebuggerPresent() || MessageBoxA(NULL, msg, "Assertion failed", MB_OKCANCEL|MB_TASKMODAL) == IDCANCEL) {
assert_kill();
} else
ExitProcess(0);
DeleteAtom(a);
#elif defined(LINUX)
kill(getpid(), SIGSEGV );
#elif defined(__APPLE__)
kill(getpid(), SIGSEGV );
#else
#error port me!
#endif
in_assert = 0;
}
#endif

1
Src/Wasabi/bfc/assert.h Normal file
View File

@ -0,0 +1 @@
#include "bfc_assert.h"

30
Src/Wasabi/bfc/bfc.sln Normal file
View File

@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29424.173
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfc", "bfc.vcxproj", "{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.Build.0 = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.ActiveCfg = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.Build.0 = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.ActiveCfg = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.Build.0 = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.ActiveCfg = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0E7F9665-971C-48B6-BF28-5952406042A2}
EndGlobalSection
EndGlobal

304
Src/Wasabi/bfc/bfc.vcxproj Normal file
View File

@ -0,0 +1,304 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}</ProjectGuid>
<RootNamespace>bfc</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..;../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;_LIB;_WIN32_WINNT=0x0601;WINVER=0x0601;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..;../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;_LIB;_WIN32_WINNT=0x0601;WINVER=0x0601;_CRT_SECURE_NO_WARNINGS;WIN64;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..;../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;_LIB;_WIN32_WINNT=0x0601;WINVER=0x0601;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..;../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;_LIB;_WIN32_WINNT=0x0601;WINVER=0x0601;_CRT_SECURE_NO_WARNINGS;WIN64;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\api\skin\xmlobject.cpp" />
<ClCompile Include="..\api\syscb\callbacks\wndcb.cpp" />
<ClCompile Include="..\api\wnd\paintcb.cpp" />
<ClCompile Include="..\api\xml\xmlwrite.cpp" />
<ClCompile Include="assert.cpp" />
<ClCompile Include="critsec.cpp" />
<ClCompile Include="depend.cpp" />
<ClCompile Include="depview.cpp" />
<ClCompile Include="file\filename.cpp" />
<ClCompile Include="file\readdir.cpp" />
<ClCompile Include="file\recursedir.cpp" />
<ClCompile Include="file\wildcharsenum.cpp" />
<ClCompile Include="foreach.cpp" />
<ClCompile Include="freelist.cpp" />
<ClCompile Include="loadlib.cpp" />
<ClCompile Include="memblock.cpp" />
<ClCompile Include="node.cpp" />
<ClCompile Include="nsguid.cpp" />
<ClCompile Include="parse\hierarchyparser.cpp" />
<ClCompile Include="parse\paramparser.cpp" />
<ClCompile Include="parse\pathparse.cpp" />
<ClCompile Include="parse\PathParseW.cpp" />
<ClCompile Include="platform\platform.cpp" />
<ClCompile Include="precomp_wasabi_bfc.cpp" />
<ClCompile Include="ptrlist.cpp" />
<ClCompile Include="stack.cpp" />
<ClCompile Include="std_string.cpp" />
<ClCompile Include="wasabi_std.cpp" />
<ClCompile Include="std_keyboard.cpp" />
<ClCompile Include="std_math.cpp" />
<ClCompile Include="wasabi_std_rect.cpp" />
<ClCompile Include="std_wnd.cpp" />
<ClCompile Include="string\bigstring.cpp" />
<ClCompile Include="string\encodedstr.cpp" />
<ClCompile Include="string\PathString.cpp" />
<ClCompile Include="string\playstring.cpp" />
<ClCompile Include="string\string.cpp" />
<ClCompile Include="string\StringW.cpp" />
<ClCompile Include="string\url.cpp" />
<ClCompile Include="string\utf8.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="util\base64.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\api\xml\xmlwrite.h" />
<ClInclude Include="assert.h" />
<ClInclude Include="bitlist.h" />
<ClInclude Include="common.h" />
<ClInclude Include="critsec.h" />
<ClInclude Include="depend.h" />
<ClInclude Include="depview.h" />
<ClInclude Include="dispatch.h" />
<ClInclude Include="file\filename.h" />
<ClInclude Include="file\readdir.h" />
<ClInclude Include="file\recursedir.h" />
<ClInclude Include="file\tmpnamestr.h" />
<ClInclude Include="file\wildcharsenum.h" />
<ClInclude Include="foreach.h" />
<ClInclude Include="freelist.h" />
<ClInclude Include="loadlib.h" />
<ClInclude Include="memblock.h" />
<ClInclude Include="multipatch.h" />
<ClInclude Include="named.h" />
<ClInclude Include="node.h" />
<ClInclude Include="nsguid.h" />
<ClInclude Include="pair.h" />
<ClInclude Include="parse\hierarchyparser.h" />
<ClInclude Include="parse\paramparser.h" />
<ClInclude Include="parse\pathparse.h" />
<ClInclude Include="platform\guid.h" />
<ClInclude Include="platform\platform.h" />
<ClInclude Include="platform\types.h" />
<ClInclude Include="platform\win32.h" />
<ClInclude Include="precomp_wasabi_bfc.h" />
<ClInclude Include="ptrlist.h" />
<ClInclude Include="reentryfilter.h" />
<ClInclude Include="stack.h" />
<ClInclude Include="std_string.h" />
<ClInclude Include="wasabi_std.h" />
<ClInclude Include="std_keyboard.h" />
<ClInclude Include="std_math.h" />
<ClInclude Include="std_mem.h" />
<ClInclude Include="std_mkncc.h" />
<ClInclude Include="wasabi_std_rect.h" />
<ClInclude Include="wasabi_std_wnd.h" />
<ClInclude Include="string\bigstring.h" />
<ClInclude Include="string\encodedstr.h" />
<ClInclude Include="string\PathString.h" />
<ClInclude Include="string\playstring.h" />
<ClInclude Include="string\stringdict.h" />
<ClInclude Include="string\StringW.h" />
<ClInclude Include="string\url.h" />
<ClInclude Include="string\utf8.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="tlist.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,330 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="assert.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="util\base64.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="critsec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="depend.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="depview.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="foreach.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="freelist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="loadlib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="memblock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="node.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="nsguid.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\api\wnd\paintcb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="precomp_wasabi_bfc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ptrlist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wasabi_std.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="std_keyboard.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="std_math.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wasabi_std_rect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="std_wnd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\api\syscb\callbacks\wndcb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\api\skin\xmlobject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\api\xml\xmlwrite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="file\filename.cpp">
<Filter>Source Files\file</Filter>
</ClCompile>
<ClCompile Include="file\readdir.cpp">
<Filter>Source Files\file</Filter>
</ClCompile>
<ClCompile Include="file\recursedir.cpp">
<Filter>Source Files\file</Filter>
</ClCompile>
<ClCompile Include="file\wildcharsenum.cpp">
<Filter>Source Files\file</Filter>
</ClCompile>
<ClCompile Include="parse\hierarchyparser.cpp">
<Filter>Source Files\parse</Filter>
</ClCompile>
<ClCompile Include="parse\pathparse.cpp">
<Filter>Source Files\parse</Filter>
</ClCompile>
<ClCompile Include="parse\PathParseW.cpp">
<Filter>Source Files\parse</Filter>
</ClCompile>
<ClCompile Include="parse\paramparser.cpp">
<Filter>Source Files\parse</Filter>
</ClCompile>
<ClCompile Include="platform\platform.cpp">
<Filter>Source Files\platform</Filter>
</ClCompile>
<ClCompile Include="string\bigstring.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\encodedstr.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\PathString.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\playstring.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\string.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\StringW.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\url.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="string\utf8.cpp">
<Filter>Source Files\string</Filter>
</ClCompile>
<ClCompile Include="std_string.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="assert.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="bitlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="critsec.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="depend.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="depview.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dispatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="foreach.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="freelist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="loadlib.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="memblock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="multipatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="named.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="node.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nsguid.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pair.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="precomp_wasabi_bfc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ptrlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="reentryfilter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabi_std.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="std_keyboard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="std_math.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="std_mem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="std_mkncc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabi_std_rect.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabi_std_wnd.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\api\xml\xmlwrite.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="file\filename.h">
<Filter>Header Files\file</Filter>
</ClInclude>
<ClInclude Include="file\readdir.h">
<Filter>Header Files\file</Filter>
</ClInclude>
<ClInclude Include="file\recursedir.h">
<Filter>Header Files\file</Filter>
</ClInclude>
<ClInclude Include="file\tmpnamestr.h">
<Filter>Header Files\file</Filter>
</ClInclude>
<ClInclude Include="file\wildcharsenum.h">
<Filter>Header Files\file</Filter>
</ClInclude>
<ClInclude Include="parse\hierarchyparser.h">
<Filter>Header Files\parse</Filter>
</ClInclude>
<ClInclude Include="parse\paramparser.h">
<Filter>Header Files\parse</Filter>
</ClInclude>
<ClInclude Include="parse\pathparse.h">
<Filter>Header Files\parse</Filter>
</ClInclude>
<ClInclude Include="platform\guid.h">
<Filter>Header Files\platform</Filter>
</ClInclude>
<ClInclude Include="platform\platform.h">
<Filter>Header Files\platform</Filter>
</ClInclude>
<ClInclude Include="platform\types.h">
<Filter>Header Files\platform</Filter>
</ClInclude>
<ClInclude Include="platform\win32.h">
<Filter>Header Files\platform</Filter>
</ClInclude>
<ClInclude Include="string\bigstring.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\encodedstr.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\PathString.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\playstring.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\stringdict.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\StringW.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\url.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="string\utf8.h">
<Filter>Header Files\string</Filter>
</ClInclude>
<ClInclude Include="std_string.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{ea13d5da-ba29-4aba-9cc6-513111cdccdd}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{98c6da9b-0ae2-4651-b2b7-d18955ab070b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{eb99ed8d-24b3-49f4-a133-2230d8639174}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\file">
<UniqueIdentifier>{25082a5c-f115-4e1b-ab9d-8e4839d35387}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\file">
<UniqueIdentifier>{fc562171-49a0-4835-a294-bb908d57d63a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\parse">
<UniqueIdentifier>{f238eb6c-4230-48b8-b26f-5c9ac444ba78}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\parse">
<UniqueIdentifier>{23d80b59-49ab-47a0-ad85-42ca540d3292}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\platform">
<UniqueIdentifier>{115977e8-a187-48e9-ac59-c71015d1fc43}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\platform">
<UniqueIdentifier>{3f34098f-2b62-4216-8c91-f0ecc8b4ccb3}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\string">
<UniqueIdentifier>{980a7b39-f9e8-42a1-91e3-409438cc880d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\string">
<UniqueIdentifier>{b693b9e8-2d93-47bf-9f05-75e1becf6a89}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\util">
<UniqueIdentifier>{509bf000-4810-4f14-8f2e-4f7aa9e9b1a1}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\draw">
<UniqueIdentifier>{1822ef05-8dbd-4088-828b-07246221f95e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\draw">
<UniqueIdentifier>{1bd5a793-ec99-4a4b-a886-8a2f97805864}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,420 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
0C165B5C0BDDA30D00D223E0 /* foreach.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165B5A0BDDA30D00D223E0 /* foreach.cpp */; };
0C165B5D0BDDA30D00D223E0 /* foreach.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165B5B0BDDA30D00D223E0 /* foreach.h */; };
0C165BEC0BDDA54300D223E0 /* memblock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165BEA0BDDA54300D223E0 /* memblock.cpp */; };
0C165BED0BDDA54300D223E0 /* memblock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165BEB0BDDA54300D223E0 /* memblock.h */; };
0C165C100BDDA5EF00D223E0 /* ptrlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165C0E0BDDA5EF00D223E0 /* ptrlist.h */; };
0C165C110BDDA5EF00D223E0 /* ptrlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165C0F0BDDA5EF00D223E0 /* ptrlist.cpp */; };
0C165C150BDDA60100D223E0 /* std_string_osx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165C130BDDA60100D223E0 /* std_string_osx.cpp */; };
0C165C220BDDA62500D223E0 /* stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165C200BDDA62500D223E0 /* stack.cpp */; };
0C165C230BDDA62500D223E0 /* stack.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165C210BDDA62500D223E0 /* stack.h */; };
0C165C270BDDA63900D223E0 /* std.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165C250BDDA63900D223E0 /* std.cpp */; };
0C165C280BDDA63900D223E0 /* std.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165C260BDDA63900D223E0 /* std.h */; };
0C165CA60BDDAA7D00D223E0 /* std_rect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165CA40BDDAA7D00D223E0 /* std_rect.cpp */; };
0C165CA70BDDAA7D00D223E0 /* std_rect.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165CA50BDDAA7D00D223E0 /* std_rect.h */; };
0C165CAE0BDDAA9100D223E0 /* std_wnd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C165CAC0BDDAA9100D223E0 /* std_wnd.cpp */; };
0C165CAF0BDDAA9100D223E0 /* std_wnd.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C165CAD0BDDAA9100D223E0 /* std_wnd.h */; };
0C1A569C0BE8380B004EB596 /* std_keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C1A569A0BE8380B004EB596 /* std_keyboard.h */; };
0C1A569D0BE8380B004EB596 /* std_keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C1A569B0BE8380B004EB596 /* std_keyboard.cpp */; };
0C2D19A90C0BE18400ED9158 /* critsec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19A80C0BE18400ED9158 /* critsec.cpp */; };
0C34965D0BDDB1CE00806EE5 /* paramparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C34965B0BDDB1CE00806EE5 /* paramparser.cpp */; };
0C34965E0BDDB1CE00806EE5 /* paramparser.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C34965C0BDDB1CE00806EE5 /* paramparser.h */; };
0C34966E0BDDB20600806EE5 /* hierarchyparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C34966C0BDDB20600806EE5 /* hierarchyparser.cpp */; };
0C34966F0BDDB20600806EE5 /* hierarchyparser.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C34966D0BDDB20600806EE5 /* hierarchyparser.h */; };
0C3496790BDDB22F00806EE5 /* PathParseW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C3496780BDDB22F00806EE5 /* PathParseW.cpp */; };
0C3496910BDDB2F800806EE5 /* depend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C34968F0BDDB2F800806EE5 /* depend.cpp */; };
0C3496920BDDB2F800806EE5 /* depend.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C3496900BDDB2F800806EE5 /* depend.h */; };
0C3496960BDDB30500806EE5 /* depview.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C3496940BDDB30500806EE5 /* depview.cpp */; };
0C3496970BDDB30500806EE5 /* depview.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C3496950BDDB30500806EE5 /* depview.h */; };
0C5425030C1398DE00F2D2CC /* string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5425010C1398DE00F2D2CC /* string.cpp */; };
0C7926BF0BF7C65600EB510B /* wildcharsenum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C7926BD0BF7C65600EB510B /* wildcharsenum.cpp */; };
0C7926C00BF7C65600EB510B /* wildcharsenum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C7926BE0BF7C65600EB510B /* wildcharsenum.h */; };
0C92FCA80BF41F6000D5B70C /* gradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C92FCA60BF41F6000D5B70C /* gradient.cpp */; };
0C92FCA90BF41F6000D5B70C /* gradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C92FCA70BF41F6000D5B70C /* gradient.h */; };
0CAAB89B0BE5473700EDF43D /* playstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CAAB8990BE5473700EDF43D /* playstring.cpp */; };
0CAAB89C0BE5473700EDF43D /* playstring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CAAB89A0BE5473700EDF43D /* playstring.h */; };
0CAAB8C00BE5482E00EDF43D /* filename.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CAAB8BE0BE5482E00EDF43D /* filename.h */; };
0CAAB8C10BE5482E00EDF43D /* filename.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CAAB8BF0BE5482E00EDF43D /* filename.cpp */; };
0CAAB8FA0BE5490C00EDF43D /* StringW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CAAB8F80BE5490C00EDF43D /* StringW.cpp */; };
0CAAB8FB0BE5490C00EDF43D /* StringW.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CAAB8F90BE5490C00EDF43D /* StringW.h */; };
0CB242CE0BF7884E006C6DD0 /* assert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CB242CC0BF7884E006C6DD0 /* assert.cpp */; };
0CC1B69B0BEE870C0082991E /* std_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC1B69A0BEE870C0082991E /* std_file.h */; };
0CC1B6B10BEE877A0082991E /* std_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CC1B6B00BEE877A0082991E /* std_file.cpp */; };
0CCF0E3A0C000D1100B207E8 /* nsguid.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCF0E380C000D1100B207E8 /* nsguid.h */; };
0CCF0E3B0C000D1100B207E8 /* nsguid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCF0E390C000D1100B207E8 /* nsguid.cpp */; };
0CCF0E9E0C00129E00B207E8 /* url.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCF0E9C0C00129E00B207E8 /* url.h */; };
0CCF0E9F0C00129E00B207E8 /* url.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCF0E9D0C00129E00B207E8 /* url.cpp */; };
0CE6AE520BDD9EEC0077EB3C /* critsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE6AE500BDD9EEC0077EB3C /* critsec.h */; };
D2AAC0700554677100DB518D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB77AAFE841565C02AAC07 /* Carbon.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
08FB77AAFE841565C02AAC07 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
0C165B5A0BDDA30D00D223E0 /* foreach.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = foreach.cpp; sourceTree = "<group>"; };
0C165B5B0BDDA30D00D223E0 /* foreach.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = foreach.h; sourceTree = "<group>"; };
0C165BEA0BDDA54300D223E0 /* memblock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = memblock.cpp; sourceTree = "<group>"; };
0C165BEB0BDDA54300D223E0 /* memblock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = memblock.h; sourceTree = "<group>"; };
0C165C0E0BDDA5EF00D223E0 /* ptrlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ptrlist.h; sourceTree = "<group>"; };
0C165C0F0BDDA5EF00D223E0 /* ptrlist.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ptrlist.cpp; sourceTree = "<group>"; };
0C165C130BDDA60100D223E0 /* std_string_osx.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = std_string_osx.cpp; path = platform/std_string_osx.cpp; sourceTree = "<group>"; };
0C165C200BDDA62500D223E0 /* stack.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = stack.cpp; sourceTree = "<group>"; };
0C165C210BDDA62500D223E0 /* stack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack.h; sourceTree = "<group>"; };
0C165C250BDDA63900D223E0 /* std.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = std.cpp; sourceTree = "<group>"; };
0C165C260BDDA63900D223E0 /* std.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = std.h; sourceTree = "<group>"; };
0C165CA40BDDAA7D00D223E0 /* std_rect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = std_rect.cpp; sourceTree = "<group>"; };
0C165CA50BDDAA7D00D223E0 /* std_rect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = std_rect.h; sourceTree = "<group>"; };
0C165CAC0BDDAA9100D223E0 /* std_wnd.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = std_wnd.cpp; sourceTree = "<group>"; };
0C165CAD0BDDAA9100D223E0 /* std_wnd.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = std_wnd.h; sourceTree = "<group>"; };
0C1A569A0BE8380B004EB596 /* std_keyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = std_keyboard.h; sourceTree = "<group>"; };
0C1A569B0BE8380B004EB596 /* std_keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = std_keyboard.cpp; sourceTree = "<group>"; };
0C2D19A80C0BE18400ED9158 /* critsec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = critsec.cpp; sourceTree = "<group>"; };
0C34965B0BDDB1CE00806EE5 /* paramparser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = paramparser.cpp; path = parse/paramparser.cpp; sourceTree = "<group>"; };
0C34965C0BDDB1CE00806EE5 /* paramparser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = paramparser.h; path = parse/paramparser.h; sourceTree = "<group>"; };
0C34966C0BDDB20600806EE5 /* hierarchyparser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = hierarchyparser.cpp; path = parse/hierarchyparser.cpp; sourceTree = "<group>"; };
0C34966D0BDDB20600806EE5 /* hierarchyparser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hierarchyparser.h; path = parse/hierarchyparser.h; sourceTree = "<group>"; };
0C3496780BDDB22F00806EE5 /* PathParseW.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PathParseW.cpp; path = parse/PathParseW.cpp; sourceTree = "<group>"; };
0C34968F0BDDB2F800806EE5 /* depend.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = depend.cpp; sourceTree = "<group>"; };
0C3496900BDDB2F800806EE5 /* depend.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = depend.h; sourceTree = "<group>"; };
0C3496940BDDB30500806EE5 /* depview.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = depview.cpp; sourceTree = "<group>"; };
0C3496950BDDB30500806EE5 /* depview.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = depview.h; sourceTree = "<group>"; };
0C5425010C1398DE00F2D2CC /* string.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string.cpp; path = string/string.cpp; sourceTree = "<group>"; };
0C7926BD0BF7C65600EB510B /* wildcharsenum.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wildcharsenum.cpp; path = file/wildcharsenum.cpp; sourceTree = "<group>"; };
0C7926BE0BF7C65600EB510B /* wildcharsenum.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wildcharsenum.h; path = file/wildcharsenum.h; sourceTree = "<group>"; };
0C92FCA60BF41F6000D5B70C /* gradient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = gradient.cpp; path = draw/gradient.cpp; sourceTree = "<group>"; };
0C92FCA70BF41F6000D5B70C /* gradient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gradient.h; path = draw/gradient.h; sourceTree = "<group>"; };
0CAAB8990BE5473700EDF43D /* playstring.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = playstring.cpp; path = string/playstring.cpp; sourceTree = "<group>"; };
0CAAB89A0BE5473700EDF43D /* playstring.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = playstring.h; path = string/playstring.h; sourceTree = "<group>"; };
0CAAB8BE0BE5482E00EDF43D /* filename.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = filename.h; path = file/filename.h; sourceTree = "<group>"; };
0CAAB8BF0BE5482E00EDF43D /* filename.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = filename.cpp; path = file/filename.cpp; sourceTree = "<group>"; };
0CAAB8F80BE5490C00EDF43D /* StringW.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = StringW.cpp; path = string/StringW.cpp; sourceTree = "<group>"; };
0CAAB8F90BE5490C00EDF43D /* StringW.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = StringW.h; path = string/StringW.h; sourceTree = "<group>"; };
0CB242CC0BF7884E006C6DD0 /* assert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = assert.cpp; sourceTree = "<group>"; };
0CC1B69A0BEE870C0082991E /* std_file.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = std_file.h; sourceTree = "<group>"; };
0CC1B6B00BEE877A0082991E /* std_file.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = std_file.cpp; sourceTree = "<group>"; };
0CCF0E380C000D1100B207E8 /* nsguid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nsguid.h; sourceTree = "<group>"; };
0CCF0E390C000D1100B207E8 /* nsguid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = nsguid.cpp; sourceTree = "<group>"; };
0CCF0E9C0C00129E00B207E8 /* url.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = url.h; path = string/url.h; sourceTree = "<group>"; };
0CCF0E9D0C00129E00B207E8 /* url.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = url.cpp; path = string/url.cpp; sourceTree = "<group>"; };
0CE6AE500BDD9EEC0077EB3C /* critsec.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = critsec.h; sourceTree = "<group>"; };
D2AAC06F0554671400DB518D /* libbfc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libbfc.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D2AAC06D0554671400DB518D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D2AAC0700554677100DB518D /* Carbon.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
034768DDFF38A45A11DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
D2AAC06F0554671400DB518D /* libbfc.a */,
);
name = Products;
sourceTree = "<group>";
};
0867D691FE84028FC02AAC07 /* bfc */ = {
isa = PBXGroup;
children = (
08FB77ACFE841707C02AAC07 /* Source */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
034768DDFF38A45A11DB9C8B /* Products */,
);
name = bfc;
sourceTree = "<group>";
};
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
08FB77AAFE841565C02AAC07 /* Carbon.framework */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
08FB77ACFE841707C02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
0CCF0DFC0C0006F100B207E8 /* file */,
0CB242CC0BF7884E006C6DD0 /* assert.cpp */,
0C2D19A80C0BE18400ED9158 /* critsec.cpp */,
0CE6AE500BDD9EEC0077EB3C /* critsec.h */,
0C34968F0BDDB2F800806EE5 /* depend.cpp */,
0C3496900BDDB2F800806EE5 /* depend.h */,
0C3496940BDDB30500806EE5 /* depview.cpp */,
0C3496950BDDB30500806EE5 /* depview.h */,
0C165B5A0BDDA30D00D223E0 /* foreach.cpp */,
0C165B5B0BDDA30D00D223E0 /* foreach.h */,
0C92FCA60BF41F6000D5B70C /* gradient.cpp */,
0C92FCA70BF41F6000D5B70C /* gradient.h */,
0C34966C0BDDB20600806EE5 /* hierarchyparser.cpp */,
0C34966D0BDDB20600806EE5 /* hierarchyparser.h */,
0C165BEA0BDDA54300D223E0 /* memblock.cpp */,
0C165BEB0BDDA54300D223E0 /* memblock.h */,
0C34965B0BDDB1CE00806EE5 /* paramparser.cpp */,
0C34965C0BDDB1CE00806EE5 /* paramparser.h */,
0C3496780BDDB22F00806EE5 /* PathParseW.cpp */,
0CAAB8990BE5473700EDF43D /* playstring.cpp */,
0CAAB89A0BE5473700EDF43D /* playstring.h */,
0C165C0F0BDDA5EF00D223E0 /* ptrlist.cpp */,
0C165C0E0BDDA5EF00D223E0 /* ptrlist.h */,
0C165C200BDDA62500D223E0 /* stack.cpp */,
0C165C210BDDA62500D223E0 /* stack.h */,
0CCF0E380C000D1100B207E8 /* nsguid.h */,
0CCF0E390C000D1100B207E8 /* nsguid.cpp */,
0C7926BD0BF7C65600EB510B /* wildcharsenum.cpp */,
0C7926BE0BF7C65600EB510B /* wildcharsenum.h */,
0CC1B67D0BEE86590082991E /* Std */,
0C3064600BEE9BB7006CF130 /* String */,
);
name = Source;
sourceTree = "<group>";
};
0C3064600BEE9BB7006CF130 /* String */ = {
isa = PBXGroup;
children = (
0C5425010C1398DE00F2D2CC /* string.cpp */,
0CCF0E9C0C00129E00B207E8 /* url.h */,
0CCF0E9D0C00129E00B207E8 /* url.cpp */,
0CAAB8F80BE5490C00EDF43D /* StringW.cpp */,
0CAAB8F90BE5490C00EDF43D /* StringW.h */,
);
name = String;
sourceTree = "<group>";
};
0CC1B67D0BEE86590082991E /* Std */ = {
isa = PBXGroup;
children = (
0C165C130BDDA60100D223E0 /* std_string_osx.cpp */,
0C165C250BDDA63900D223E0 /* std.cpp */,
0CC1B6B00BEE877A0082991E /* std_file.cpp */,
0CC1B69A0BEE870C0082991E /* std_file.h */,
0C165C260BDDA63900D223E0 /* std.h */,
0C165CA40BDDAA7D00D223E0 /* std_rect.cpp */,
0C165CA50BDDAA7D00D223E0 /* std_rect.h */,
0C165CAC0BDDAA9100D223E0 /* std_wnd.cpp */,
0C165CAD0BDDAA9100D223E0 /* std_wnd.h */,
0C1A569A0BE8380B004EB596 /* std_keyboard.h */,
0C1A569B0BE8380B004EB596 /* std_keyboard.cpp */,
);
name = Std;
sourceTree = "<group>";
};
0CCF0DFC0C0006F100B207E8 /* file */ = {
isa = PBXGroup;
children = (
0CAAB8BF0BE5482E00EDF43D /* filename.cpp */,
0CAAB8BE0BE5482E00EDF43D /* filename.h */,
);
name = file;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D2AAC06B0554671400DB518D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0CE6AE520BDD9EEC0077EB3C /* critsec.h in Headers */,
0C165B5D0BDDA30D00D223E0 /* foreach.h in Headers */,
0C165BED0BDDA54300D223E0 /* memblock.h in Headers */,
0C165C100BDDA5EF00D223E0 /* ptrlist.h in Headers */,
0C165C230BDDA62500D223E0 /* stack.h in Headers */,
0C165C280BDDA63900D223E0 /* std.h in Headers */,
0C165CA70BDDAA7D00D223E0 /* std_rect.h in Headers */,
0C165CAF0BDDAA9100D223E0 /* std_wnd.h in Headers */,
0C34965E0BDDB1CE00806EE5 /* paramparser.h in Headers */,
0C34966F0BDDB20600806EE5 /* hierarchyparser.h in Headers */,
0C3496920BDDB2F800806EE5 /* depend.h in Headers */,
0C3496970BDDB30500806EE5 /* depview.h in Headers */,
0CAAB89C0BE5473700EDF43D /* playstring.h in Headers */,
0CAAB8C00BE5482E00EDF43D /* filename.h in Headers */,
0CAAB8FB0BE5490C00EDF43D /* StringW.h in Headers */,
0C1A569C0BE8380B004EB596 /* std_keyboard.h in Headers */,
0CC1B69B0BEE870C0082991E /* std_file.h in Headers */,
0C92FCA90BF41F6000D5B70C /* gradient.h in Headers */,
0C7926C00BF7C65600EB510B /* wildcharsenum.h in Headers */,
0CCF0E3A0C000D1100B207E8 /* nsguid.h in Headers */,
0CCF0E9E0C00129E00B207E8 /* url.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D2AAC06E0554671400DB518D /* bfc */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB920108733DBB0010E9CD /* Build configuration list for PBXNativeTarget "bfc" */;
buildPhases = (
D2AAC06B0554671400DB518D /* Headers */,
D2AAC06C0554671400DB518D /* Sources */,
D2AAC06D0554671400DB518D /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = bfc;
productName = bfc;
productReference = D2AAC06F0554671400DB518D /* libbfc.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB920508733DBB0010E9CD /* Build configuration list for PBXProject "bfc" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 0867D691FE84028FC02AAC07 /* bfc */;
productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D2AAC06E0554671400DB518D /* bfc */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
D2AAC06C0554671400DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0C165B5C0BDDA30D00D223E0 /* foreach.cpp in Sources */,
0C165BEC0BDDA54300D223E0 /* memblock.cpp in Sources */,
0C165C110BDDA5EF00D223E0 /* ptrlist.cpp in Sources */,
0C165C150BDDA60100D223E0 /* std_string_osx.cpp in Sources */,
0C165C220BDDA62500D223E0 /* stack.cpp in Sources */,
0C165C270BDDA63900D223E0 /* std.cpp in Sources */,
0C165CA60BDDAA7D00D223E0 /* std_rect.cpp in Sources */,
0C165CAE0BDDAA9100D223E0 /* std_wnd.cpp in Sources */,
0C34965D0BDDB1CE00806EE5 /* paramparser.cpp in Sources */,
0C34966E0BDDB20600806EE5 /* hierarchyparser.cpp in Sources */,
0C3496790BDDB22F00806EE5 /* PathParseW.cpp in Sources */,
0C3496910BDDB2F800806EE5 /* depend.cpp in Sources */,
0C3496960BDDB30500806EE5 /* depview.cpp in Sources */,
0CAAB89B0BE5473700EDF43D /* playstring.cpp in Sources */,
0CAAB8C10BE5482E00EDF43D /* filename.cpp in Sources */,
0CAAB8FA0BE5490C00EDF43D /* StringW.cpp in Sources */,
0C1A569D0BE8380B004EB596 /* std_keyboard.cpp in Sources */,
0CC1B6B10BEE877A0082991E /* std_file.cpp in Sources */,
0C92FCA80BF41F6000D5B70C /* gradient.cpp in Sources */,
0CB242CE0BF7884E006C6DD0 /* assert.cpp in Sources */,
0C7926BF0BF7C65600EB510B /* wildcharsenum.cpp in Sources */,
0CCF0E3B0C000D1100B207E8 /* nsguid.cpp in Sources */,
0CCF0E9F0C00129E00B207E8 /* url.cpp in Sources */,
0C2D19A90C0BE18400ED9158 /* critsec.cpp in Sources */,
0C5425030C1398DE00F2D2CC /* string.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1DEB920208733DBB0010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
INSTALL_PATH = /usr/local/lib;
OTHER_CPLUSPLUSFLAGS = "-fpermissive";
PRODUCT_NAME = bfc;
ZERO_LINK = YES;
};
name = Debug;
};
1DEB920308733DBB0010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
ppc,
i386,
);
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "";
INSTALL_PATH = /usr/local/lib;
OTHER_CPLUSPLUSFLAGS = "-fpermissive";
PRODUCT_NAME = bfc;
};
name = Release;
};
1DEB920608733DBB0010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
..,
../..,
);
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
name = Debug;
};
1DEB920708733DBB0010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
..,
../..,
);
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB920108733DBB0010E9CD /* Build configuration list for PBXNativeTarget "bfc" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB920208733DBB0010E9CD /* Debug */,
1DEB920308733DBB0010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB920508733DBB0010E9CD /* Build configuration list for PBXProject "bfc" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB920608733DBB0010E9CD /* Debug */,
1DEB920708733DBB0010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}

View File

@ -0,0 +1,39 @@
#ifndef _ASSERT_H
#define _ASSERT_H
#include <bfc/wasabi_std.h>
#ifdef CPLUSPLUS
extern "C" {
#endif
COMEXP void _assert_handler(const char *reason, const char *file, int line);
COMEXP void _assert_handler_str(const char *string, const char *reason, const char *file, int line);
#ifdef CPLUSPLUS
}
#endif
#ifdef ASSERT
#undef ASSERT
#endif
// benski> added june 7 2007.. somewhat of a hack - don't want to enable assert's for final builds
#include "../../Winamp/buildtype.h"
#if defined(_DEBUG) /*|| defined(INTERNAL) */|| defined(BETA)
#define ASSERTS_ENABLED
#endif
#ifdef ASSERTS_ENABLED
#define ASSERT(x) ((x) ? void() : _assert_handler(#x, __FILE__, __LINE__))
#define ASSERTPR(x, str) ((x) ? void() : _assert_handler_str((str), #x, __FILE__, __LINE__))
#define ASSERTALWAYS(str) _assert_handler_str((str), 0, __FILE__, __LINE__)
#else
#define ASSERT(x) ;
#define ASSERTPR(x,y) ;
#define ASSERTALWAYS ;
#endif
#endif

41
Src/Wasabi/bfc/bitlist.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef _BITLIST_H
#define _BITLIST_H
#include "memblock.h"
class BitList {
public:
BitList(unsigned int size=0) {
setSize(size);
}
int getitem(int n) const {
if (n < 0 || n >= m_size) return 0;
return (m_list[n>>3]>>(n&7))&1;
}
void setitem(int n, int v) {
if (n >= 0 && n < m_size) {
int lv=1<<(n&7);
if (v) m_list[n>>3]|=lv;
else m_list[n>>3]&=~lv;
}
}
int operator[](int n) const { return getitem(n); }
int getSize() const { // in bits
return m_size;
}
void setSize(unsigned int newsize) {
m_list.setSize((newsize+7)>>3);
m_size = newsize;
}
int getsize() const { return m_size; }
private:
MemBlock< uint8_t> m_list;
int m_size;
};
#endif

23
Src/Wasabi/bfc/common.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _COMMON_H
#define _COMMON_H
#ifdef WIN32
// disable "dll-interface to be used by clients of class" warning message.
#pragma warning(disable: 4251)
#endif /* WIN32 */
#ifdef COMEXP
#undef COMEXP
#endif
#define COMEXP
#ifndef __cplusplus
#define EXTC extern
#else
#define EXTC extern "C"
#endif
#include <bfc/wasabi_std.h>
#endif /* _COMMON_H */

View File

@ -0,0 +1,73 @@
#include "precomp_wasabi_bfc.h"
#include "critsec.h"
// uncomment this if needed
//#define CS_DEBUG
CriticalSection::CriticalSection() {
#ifdef WIN32
InitializeCriticalSection(&cs);
#elif defined(__APPLE__)
MPCreateCriticalRegion(&cr);
#elif defined(LINUX)
pthread_mutex_t recursive = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
cs.mutex = recursive;
#endif
#ifdef ASSERTS_ENABLED
#ifdef CS_DEBUG
within = 0;
#endif
#endif
}
CriticalSection::~CriticalSection() {
#ifdef CS_DEBUG
#ifdef ASSERTS_ENABLED
ASSERT(!within);
#endif
#endif
#ifdef WIN32
DeleteCriticalSection(&cs);
#elif defined(__APPLE__)
MPDeleteCriticalRegion(cr);
#elif defined(LINUX)
pthread_mutex_destroy(&cs.mutex);
#endif
}
void CriticalSection::enter() {
#ifdef WIN32
EnterCriticalSection(&cs);
#elif defined(__APPLE__)
MPEnterCriticalRegion(cr, kDurationForever);
#elif defined(LINUX)
pthread_mutex_lock(&cs.mutex);
#endif
#ifdef CS_DEBUG
#ifdef ASSERTS_ENABLED
ASSERT(!within);
within = 1;
#endif
#endif
}
void CriticalSection::leave() {
#if defined(CS_DEBUG) && defined(ASSERTS_ENABLED)
ASSERT(within);
within = 0;
#endif
#ifdef WIN32
LeaveCriticalSection(&cs);
#elif defined(__APPLE__)
MPExitCriticalRegion(cr);
#elif defined(LINUX)
pthread_mutex_unlock(&cs.mutex);
#endif
}
void CriticalSection::inout() {
enter();
leave();
}

96
Src/Wasabi/bfc/critsec.h Normal file
View File

@ -0,0 +1,96 @@
#ifndef _CRITSEC_H
#define _CRITSEC_H
#ifdef _WIN32
#include <windows.h>
#elif defined(__APPLE__)
#include <CoreServices/CoreServices.h>
#endif
#include <bfc/common.h>
#include <bfc/bfc_assert.h>
/**
CriticalSection is a portable object that implements a critical section,
which is to say, it ensures that no two threads can be in that same
section of code at the same time. Usually you make them a global object
or allocate them with new and pass them to both threads.
@short Critical section class.
@author Nullsoft
@ver 1.0
@see Thread
@see InCriticalSection
*/
class CriticalSection {
public:
CriticalSection();
virtual ~CriticalSection();
/**
Enters the critical section. If another thread is already in the critical
section, the calling thread will be blocked until the other thread calls
leave().
@see leave()
*/
void enter();
/**
Leaves the critical section. If another thread is currently blocked on
this critical section, it will be unblocked. If multiple threads are blocking
only one will be unblocked.
@see enter()
*/
void leave();
/**
Calls enter() and leave() in quick succession. Useful to make sure that no
other thread is in the critical section (although another thread could
immediately re-enter)
@see enter()
@see leave()
*/
void inout();
private:
#ifdef ASSERTS_ENABLED
int within;
#endif
#ifdef _WIN32
CRITICAL_SECTION cs;
#elif defined(__APPLE__)
MPCriticalRegionID cr;
#endif
};
/**
This is a little helper class to ease the use of class CriticalSection.
When it is instantiated, it enters a given critical section. When it is
destroyed, it leaves the given critical section.
CriticalSection a_cs;
void blah() {
InCriticalSection cs(a_cs); // critical section protection begins
if (test) {
return 0; // critical section protection ends
}
// critical section protection still active!
doSomething();
return 1; // critical section protection ends
}
@author Nullsoft
@see CriticalSection
*/
class InCriticalSection {
public:
InCriticalSection(CriticalSection *cs) : m_cs(cs) { m_cs->enter(); }
InCriticalSection(CriticalSection &cs) : m_cs(&cs) { m_cs->enter(); }
~InCriticalSection() { m_cs->leave(); }
private:
CriticalSection *m_cs;
};
#define _INCRITICALSECTION(id, x) InCriticalSection __I_C_S__##id(x)
#define INCRITICALSECTION(x) _INCRITICALSECTION(__LINE__, x)
#endif

211
Src/Wasabi/bfc/depend.cpp Normal file
View File

@ -0,0 +1,211 @@
#include "precomp_wasabi_bfc.h"
#include "depend.h"
#include "platform/guid.h"
DependentViewerI::DependentViewerI() : viewed_items(NULL) { }
DependentViewerI::DependentViewerI(const DependentViewerI &dep) :
viewed_items(NULL)
{
// watch their items now
if (dep.viewed_items != NULL)
{
for (int i = 0; i < dep.viewed_items->getNumItems(); i++)
viewer_addViewItem(dep.viewed_items->enumItem(i));
}
}
DependentViewerI::~DependentViewerI()
{
if (viewed_items != NULL)
{
// tell viewed items to detach from us
foreach(viewed_items)
viewed_items->getfor()->dependent_regViewer(this, FALSE);
endfor
#if 0
for (int i = 0; i < viewed_items->getNumItems(); i++)
{
ifc_dependent *item = viewed_items->enumItem(i);
item->dependent_regViewer(this, FALSE);
}
#endif
viewed_items->removeAll();
delete viewed_items;
}
}
DependentViewerI &DependentViewerI::operator =(const DependentViewerI &dep)
{
if (this != &dep)
{
viewer_delAllItems();
// watch their items now
if (dep.viewed_items != NULL)
{
for (int i = 0; i < dep.viewed_items->getNumItems(); i++)
viewer_addViewItem(dep.viewed_items->enumItem(i));
}
}
return *this;
}
void DependentViewerI::viewer_addViewItem(ifc_dependent *item)
{
ASSERT(item != NULL);
if (viewed_items == NULL) viewed_items = new DependentList(8);
if (viewed_items->haveItem(item)) return ;
viewed_items->addItem(item);
item->dependent_regViewer(this, TRUE);
}
void DependentViewerI::viewer_delViewItem(ifc_dependent *item)
{
if (item == NULL) return ;
if (viewed_items == NULL || !viewed_items->haveItem(item)) return ;
item->dependent_regViewer(this, FALSE);
viewed_items->removeItem(item);
if (viewed_items->getNumItems() == 0)
{
delete viewed_items; viewed_items = NULL;
}
}
void DependentViewerI::viewer_delAllItems()
{
while (viewed_items != NULL)
{
ifc_dependent *item = viewer_enumViewItem(0);
if (item == NULL) break;
viewer_delViewItem(item);
}
delete viewed_items;
viewed_items = NULL;
}
void DependentViewerI::viewer_delAllOfClass(const GUID *guid)
{
if (viewed_items == NULL) return ;
foreach(viewed_items)
if (viewed_items->getfor()->dependent_getInterface(guid))
viewer_delViewItem(viewed_items->getfor());
endfor
}
ifc_dependent *DependentViewerI::viewer_enumViewItem(int which)
{
if (viewed_items == NULL) return NULL;
return viewed_items->enumItem(which);
}
int DependentViewerI::viewer_getNumItems()
{
if (viewed_items == NULL) return 0;
return viewed_items->getNumItems();
}
int DependentViewerI::viewer_haveItem(ifc_dependent *item)
{
if (viewed_items == NULL) return 0;
return viewed_items->haveItem(item);
}
int DependentViewerI::dependentViewer_callback(ifc_dependent *item, const GUID *classguid, int cb, intptr_t param1, intptr_t param2, void *ptr, size_t ptrlen)
{
if (viewed_items == NULL || !viewed_items->haveItem(item)) return 0;
switch (cb)
{
case DependentCB::DEPCB_NOP: return 1;
case DependentCB::DEPCB_DELETED:
viewed_items->removeItem(item);
return viewer_onItemDeleted(item);
case DependentCB::DEPCB_EVENT:
return viewer_onEvent(item, classguid, (int)param1, param2, ptr, ptrlen);
break;
}
return 0;
}
DependentI::DependentI(const GUID *classguid) : viewers(NULL), class_guid(classguid ? *classguid : INVALID_GUID)
{}
DependentI::DependentI(const DependentI &dep) : viewers(NULL), class_guid(dep.class_guid) { }
DependentI::~DependentI()
{
if (viewers != NULL)
{
foreach(viewers)
viewers->getfor()->dependentViewer_callback(this, &class_guid, DependentCB::DEPCB_DELETED);
endfor
delete viewers;
}
}
DependentI& DependentI::operator =(const ifc_dependent &dep)
{
// placeholder code... nobody asked to watch us
if (this != &dep)
{
viewers = NULL;
}
return *this;
}
void DependentI::dependent_regViewer(api_dependentviewer *viewer, int add)
{
if (viewer == NULL) return ;
if (add)
{
if (viewers == NULL) viewers = new ViewerList(8);
if (viewers->haveItem(viewer)) return ;
viewers->addItem(viewer);
viewer->dependentViewer_callback(this, &class_guid, DependentCB::DEPCB_NOP);
}
else
{ // delete
if (viewers == NULL) return ;
viewers->removeItem(viewer);
if (viewers->getNumItems() == 0)
{
delete viewers; viewers = NULL;
}
}
dependent_onRegViewer(viewer, add);
}
void DependentI::dependent_sendEvent(const GUID *classguid, int event, intptr_t param, void *ptr, size_t ptrlen, api_dependentviewer *viewer)
{
if (classguid == NULL) classguid = &class_guid; // use default
ASSERT(*classguid != INVALID_GUID);
sendViewerCallbacks(classguid, DependentCB::DEPCB_EVENT, event, param, ptr, ptrlen, viewer);
}
void DependentI::sendViewerCallbacks(const GUID *classguid, int msg, intptr_t param1, intptr_t param2, void *ptr, size_t ptrlen, api_dependentviewer *viewer)
{
if (viewers == NULL) return ;
ASSERT(classguid != NULL);
foreach(viewers)
if (viewer == NULL || viewer == viewers->getfor())
viewers->getfor()->dependentViewer_callback(this, classguid, msg, param1, param2, ptr, ptrlen);
endfor
}
#ifdef CBCLASS
#undef CBCLASS
#endif
#define CBCLASS DependentViewerI
START_DISPATCH;
CB(DEPENDENTVIEWER_CALLBACK, dependentViewer_callback);
END_DISPATCH;
#undef CBCLASS
#define CBCLASS DependentI
START_DISPATCH;
VCB(API_DEPENDENT_REGVIEWER, dependent_regViewer);
CB(API_DEPENDENT_GETINTERFACE, dependent_getInterface);
END_DISPATCH;
#undef CBCLASS

152
Src/Wasabi/bfc/depend.h Normal file
View File

@ -0,0 +1,152 @@
#ifndef _DEPEND_H
#define _DEPEND_H
#include <bfc/platform/platform.h>
#include <bfc/common.h>
#include <bfc/ptrlist.h>
// a pair of classes to implement data dependency. a viewer can register
// a list of things it wants to know about
// WARNING: this file is still under development. check back for changes
// in subsequent SDK releases. over time it is going to become more generic
class ifc_dependent;
#include <api/dependency/api_dependentviewer.h>
// inherit from this one
class /*NOVTABLE */DependentViewerI : public api_dependentviewer
{
protected:
/**
@param classguid If set, incoming events are restricted to those in that GUID namespace. Can be NULL.
*/
DependentViewerI();
DependentViewerI(const DependentViewerI &dep);
virtual ~DependentViewerI();
// copy
DependentViewerI &operator =(const DependentViewerI &dep);
// derived classes call this on themselves when they want to view a new item
// everything else gets handled automagically
void viewer_addViewItem(ifc_dependent *item);
void viewer_delViewItem(ifc_dependent *item);
void viewer_delAllItems();
void viewer_delAllOfClass(const GUID *guid); //only works if dependent has implemented dependent_getInterface() for the GUID
// call this whenever you need to know what you're looking at
ifc_dependent *viewer_enumViewItem(int which);
int viewer_getNumItems();
// returns TRUE if item is in our list
int viewer_haveItem(ifc_dependent *item);
// convenience callback methods
// item you were looking at is gone: WARNING: pointer no longer valid!
virtual int viewer_onItemDeleted(ifc_dependent *item) { return 1; }
// item you are looking at issuing an event
virtual int viewer_onEvent(ifc_dependent *item, const GUID *classguid, int event, intptr_t param, void *ptr, size_t ptrlen) { return 1; }
private:
// don't override this; override the individual convenience callbacks
virtual int dependentViewer_callback(ifc_dependent *item, const GUID *classguid, int cb, intptr_t param1 = 0, intptr_t param2 = 0, void *ptr = NULL, size_t ptrlen = 0);
typedef PtrList <ifc_dependent> DependentList;
DependentList * viewed_items;
protected:
RECVS_DISPATCH;
};
template <class VT>
class NOVTABLE DependentViewerT : private DependentViewerI
{
protected:
DependentViewerT() { }
DependentViewerT(VT *first)
{
if (first) viewer_addViewItem(first);
}
public:
using DependentViewerI::viewer_addViewItem;
using DependentViewerI::viewer_delViewItem;
using DependentViewerI::viewer_delAllItems;
VT *viewer_enumViewItem(int which)
{
return static_cast<VT*>(DependentViewerI::viewer_enumViewItem(which));
}
using DependentViewerI::viewer_getNumItems;
using DependentViewerI::viewer_haveItem;
// spiffy callbacks to override
// item you were looking at is gone: WARNING: pointer no longer valid!
virtual int viewer_onItemDeleted(VT *item) { return 1; }
// item you are looking at issuing an event (filtered by class guid of VT)
virtual int viewer_onEvent(VT *item, int event, intptr_t param2, void *ptr, size_t ptrlen) { return 1; }
private:
virtual int viewer_onItemDeleted(ifc_dependent *item)
{
return viewer_onItemDeleted(static_cast<VT*>(item));
}
virtual int viewer_onEvent(ifc_dependent *item, const GUID *classguid, int event, intptr_t param, void *ptr, size_t ptrlen)
{
if (*classguid != *VT::depend_getClassGuid()) return 0; // filter namespace
return viewer_onEvent(static_cast<VT*>(item), event, param, ptr, ptrlen);
}
};
// ------------------------------------------------------------
#include <api/dependency/api_dependent.h>
class NOVTABLE DependentI : public ifc_dependent
{
protected:
DependentI(const GUID *class_guid = NULL);
DependentI(const DependentI &dep);
virtual ~DependentI();
public:
// copy
DependentI& operator =(const ifc_dependent &dep);
protected:
// override this to catch when viewers register and deregister
virtual void dependent_onRegViewer(api_dependentviewer *viewer, int add) {}
// override this to help people cast you to various classes
virtual void *dependent_getInterface(const GUID *classguid) { return NULL; }
// call this on yourself to send an event
void dependent_sendEvent(const GUID *classguid, int event, intptr_t param = 0, void *ptr = NULL, size_t ptrlen = 0, api_dependentviewer *viewer = NULL);
private:
virtual void dependent_regViewer(api_dependentviewer *viewer, int add);
void sendViewerCallbacks(const GUID *classguid, int msg, intptr_t param1 = 0, intptr_t param2 = 0, void *ptr = NULL, size_t ptrlen = 0, api_dependentviewer *viewer = NULL);
typedef PtrList<api_dependentviewer> ViewerList;
ViewerList *viewers;
GUID class_guid;
protected:
RECVS_DISPATCH;
};
// use like MyClass *myobj = dynamic_guid_cast<MyClass>(some_dependent_ptr);
// MyClass::getClassGuid() must be defined
// MyClass::dependent_getInterface() must be defined too
template <class T>
class dynamic_guid_cast
{
public:
dynamic_guid_cast(ifc_dependent *_dp, const GUID *_g) : dp(_dp), g(_g) { }
operator T*()
{
return (*g == *T::depend_getClassGuid()) ? static_cast<T*>(dp->dependent_getInterface(g)) : NULL;
}
private:
ifc_dependent *dp;
const GUID *g;
};
#endif

View File

@ -0,0 +1,2 @@
#include "precomp_wasabi_bfc.h"
#include "depview.h"

103
Src/Wasabi/bfc/depview.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef _DEPVIEW_H
#define _DEPVIEW_H
#include <bfc/depend.h>
#include <map>
// this handles classes that use the getDependencyPtr() method instead of a
// public cast
template <class VT>
class NOVTABLE DependentViewerTPtr : private DependentViewerI
{
protected:
DependentViewerTPtr(VT *first = NULL)
{
_addViewItem(first);
}
void viewer_addViewItem(VT *item) { _addViewItem(item); }
void viewer_delViewItem(VT *item) { _delViewItem(item); }
using DependentViewerI::viewer_delAllItems;
VT *viewer_enumViewItem(int which)
{
return lookup(DependentViewerI::viewer_enumViewItem(which));
}
using DependentViewerI::viewer_getNumItems;
int viewer_haveItem(VT *item)
{
return DependentViewerI::viewer_haveItem(item->getDependencyPtr());
}
// item you were looking at is gone: WARNING: pointer no longer valid!
virtual int viewer_onItemDeleted(VT *item) { return 1; }
// item you are looking at issuing an event
virtual int viewer_onEvent(VT *item, int event, intptr_t param2, void *ptr, size_t ptrlen) { return 1; }
protected:
virtual int viewer_onItemDeleted(ifc_dependent *item)
{
return viewer_onItemDeleted(lookup(item));
}
virtual int viewer_onEvent(ifc_dependent *item, const GUID *classguid, int event, intptr_t param, void *ptr, size_t ptrlen)
{
if (*classguid != *VT::depend_getClassGuid()) return 0; // filter namespace
return viewer_onEvent(lookup(item), event, param, ptr, ptrlen);
}
private:
VT *lookup(ifc_dependent *d)
{
if (d == NULL)
return NULL;
VT *vt = NULL;
//int r = ptrmap.getItem(d, &vt);
auto it = ptrmap.find(d);
if (it != ptrmap.end())
{
vt = it->second;
}
//ASSERT(r);
ASSERT(vt->getDependencyPtr() == d);
return vt;
}
void _addViewItem(VT *item)
{
if (item == NULL)
return ;
ifc_dependent *d = item->getDependencyPtr();
if (d == NULL)
return ;
ptrmap.insert({ d, item });
DependentViewerI::viewer_addViewItem(d);
}
void _delViewItem(VT *item)
{
if (item == NULL) return ;
ifc_dependent *dep = NULL;
//ptrmap.reverseGetItem(item, &dep);
//int r = ptrmap.reverseDelItem(item);
for (auto &ptr : ptrmap)
{
if (ptr.second == item)
{
dep = ptr.first;
ptrmap.erase(dep);
break;
}
}
//ASSERT(r);
DependentViewerI::viewer_delViewItem(dep);
}
std::map<ifc_dependent *, VT *> ptrmap;
};
#endif

622
Src/Wasabi/bfc/dispatch.h Normal file
View File

@ -0,0 +1,622 @@
#pragma once
//#include <bfc/platform/platform.h>
#include "bfc/platform/types.h"
#include "bfc/platform/guid.h"
#ifdef WIN32
#ifndef NOVTABLE
#define NOVTABLE __declspec(novtable)
#endif
#else
#define NOVTABLE
#endif
class DispatchableCallback;
#pragma warning(disable: 4786)
#pragma warning(disable: 4275)
#pragma warning(disable: 4100)
enum
{
DISPATCH_SUCCESS = 0,
DISPATCH_FAILURE = 1,
};
class NOVTABLE Dispatchable
{
public:
// // fake virtual destructor
// void destruct() { _voidcall(DESTRUCT); }
// this is virtual so it is visible across modules
virtual int _dispatch( int msg, void *retval, void **params = 0, int nparam = 0 ) = 0;
/* added 22 May 2007. these aren't used yet. To be used in the future
in the meantime, don't use negative numbers for your msg values */
int AddRef();
int Release();
int QueryInterface( GUID interface_guid, void **object );
enum
{
ADDREF = -1,
RELEASE = -2,
QUERYINTERFACE = -3,
};
protected:
// // protected real destructor
// ~Dispatchable() {}
// helper templates to implement client-side methods
int _voidcall( int msg )
{
return _dispatch( msg, 0 );
}
template<class PARAM1>
int _voidcall( int msg, PARAM1 param1 )
{
void *params[ 1 ] = { &param1 };
return _dispatch( msg, 0, params, 1 );
}
template<class PARAM1, class PARAM2>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2 )
{
void *params[ 2 ] = { &param1, &param2 };
return _dispatch( msg, 0, params, 2 );
}
template<class PARAM1, class PARAM2, class PARAM3>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3 )
{
void *params[ 3 ] = { &param1, &param2, &param3 };
return _dispatch( msg, 0, params, 3 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4 )
{
void *params[ 4 ] = { &param1, &param2, &param3, &param4 };
return _dispatch( msg, 0, params, 4 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5 )
{
// void *params[4] = { &param1, &param2, &param3, &param4, &param5 }; // mig found another bug
void *params[ 5 ] = { &param1, &param2, &param3, &param4, &param5 };
return _dispatch( msg, 0, params, 5 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6 )
{
// void *params[4] = { &param1, &param2, &param3, &param4, &param5, &param6 }; // mig found another bug
void *params[ 6 ] = { &param1, &param2, &param3, &param4, &param5, &param6 };
return _dispatch( msg, 0, params, 6 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7 )
{
void *params[ 7 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 };
return _dispatch( msg, 0, params, 7 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8 )
{
void *params[ 8 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 };
return _dispatch( msg, 0, params, 8 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9 )
{
void *params[ 9 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 , &param9 };
return _dispatch( msg, 0, params, 9 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9, PARAM10 param10 )
{
void *params[ 10 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 , &param9 , &param10 };
return _dispatch( msg, 0, params, 10 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9, PARAM10 param10, PARAM11 param11, PARAM12 param12, PARAM13 param13, PARAM14 param14 )
{
void *params[ 14 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 , &param9 , &param10 , &param11 , &param12 , &param13 , &param14 };
return _dispatch( msg, 0, params, 14 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9, PARAM10 param10, PARAM11 param11, PARAM12 param12, PARAM13 param13, PARAM14 param14, PARAM15 param15, PARAM16 param16 )
{
void *params[ 16 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 , &param9 , &param10 , &param11 , &param12 , &param13 , &param14 , &param15 , &param16 };
return _dispatch( msg, 0, params, 16 );
}
template<class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16, class PARAM17>
int _voidcall( int msg, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9, PARAM10 param10, PARAM11 param11, PARAM12 param12, PARAM13 param13, PARAM14 param14, PARAM15 param15, PARAM16 param16, PARAM17 param17 )
{
void *params[ 17 ] = { &param1, &param2, &param3, &param4, &param5, &param6 , &param7 , &param8 , &param9 , &param10 , &param11 , &param12 , &param13 , &param14 , &param15 , &param16 , &param17 };
return _dispatch( msg, 0, params, 17 );
}
template<class RETURN_TYPE>
RETURN_TYPE _call( int msg, RETURN_TYPE defval )
{
RETURN_TYPE retval;
if ( _dispatch( msg, &retval ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1 )
{
void *params[ 1 ] = { &param1 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 1 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2 )
{
void *params[ 2 ] = { &param1, &param2 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 2 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3 )
{
void *params[ 3 ] = { &param1, &param2, &param3 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 3 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4 )
{
void *params[ 4 ] = { &param1, &param2, &param3, &param4 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 4 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5 )
{
void *params[ 5 ] = { &param1, &param2, &param3, &param4, &param5 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 5 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6 )
{
void *params[ 6 ] = { &param1, &param2, &param3, &param4, &param5, &param6 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 6 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7 )
{
void *params[ 7 ] = { &param1, &param2, &param3, &param4, &param5, &param6, &param7 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 7 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8 )
{
void *params[ 8 ] = { &param1, &param2, &param3, &param4, &param5, &param6, &param7, &param8 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 8 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9 )
{
void *params[ 9 ] = { &param1, &param2, &param3, &param4, &param5, &param6, &param7, &param8, &param9 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 9 ) ) return retval;
return defval;
}
template<class RETURN_TYPE, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
RETURN_TYPE _call( int msg, RETURN_TYPE defval, PARAM1 param1, PARAM2 param2, PARAM3 param3, PARAM4 param4, PARAM5 param5, PARAM6 param6, PARAM7 param7, PARAM8 param8, PARAM9 param9, PARAM10 param10 )
{
void *params[ 10 ] = { &param1, &param2, &param3, &param4, &param5, &param6, &param7, &param8, &param9, &param10 };
RETURN_TYPE retval;
if ( _dispatch( msg, &retval, params, 10 ) ) return retval;
return defval;
}
template <class CASTNAME, class CLASSNAME, class RETVAL>
void cb( RETVAL( CLASSNAME:: *fn )( ), void *retval, void **params )
{
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( );
}
template <class CASTNAME, class CLASSNAME>
void vcb( void ( CLASSNAME:: *fn )( ), void *retval, void **params )
{
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1 );
}
template <class CASTNAME, class CLASSNAME, class PARAM1>
void vcb( void ( CLASSNAME:: *fn )( PARAM1 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1 );
}
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2 );
}
// 3 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3 );
}
// 4 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4 );
}
// 5 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5 );
}
// 6 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6 );
}
// 7 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7 );
}
// 8 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8 );
}
// 9 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9 );
}
// 10 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
PARAM10 *p10 = static_cast<PARAM10 *>( params[ 9 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10 );
}
template <class CASTNAME, class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
void cb( RETVAL( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
PARAM10 *p10 = static_cast<PARAM10 *>( params[ 9 ] );
*static_cast<RETVAL *>( retval ) = ( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10 );
}
// 14 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
PARAM10 *p10 = static_cast<PARAM10 *>( params[ 9 ] );
PARAM11 *p11 = static_cast<PARAM11 *>( params[ 10 ] );
PARAM12 *p12 = static_cast<PARAM12 *>( params[ 11 ] );
PARAM13 *p13 = static_cast<PARAM13 *>( params[ 12 ] );
PARAM14 *p14 = static_cast<PARAM14 *>( params[ 13 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14 );
}
// 16 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
PARAM10 *p10 = static_cast<PARAM10 *>( params[ 9 ] );
PARAM11 *p11 = static_cast<PARAM11 *>( params[ 10 ] );
PARAM12 *p12 = static_cast<PARAM12 *>( params[ 11 ] );
PARAM13 *p13 = static_cast<PARAM13 *>( params[ 12 ] );
PARAM14 *p14 = static_cast<PARAM14 *>( params[ 13 ] );
PARAM15 *p15 = static_cast<PARAM15 *>( params[ 14 ] );
PARAM16 *p16 = static_cast<PARAM16 *>( params[ 15 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16 );
}
// 17 params
template <class CASTNAME, class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16, class PARAM17>
void vcb( void ( CLASSNAME:: *fn )( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16, PARAM17 ), void *retval, void **params )
{
PARAM1 *p1 = static_cast<PARAM1 *>( params[ 0 ] );
PARAM2 *p2 = static_cast<PARAM2 *>( params[ 1 ] );
PARAM3 *p3 = static_cast<PARAM3 *>( params[ 2 ] );
PARAM4 *p4 = static_cast<PARAM4 *>( params[ 3 ] );
PARAM5 *p5 = static_cast<PARAM5 *>( params[ 4 ] );
PARAM6 *p6 = static_cast<PARAM6 *>( params[ 5 ] );
PARAM7 *p7 = static_cast<PARAM7 *>( params[ 6 ] );
PARAM8 *p8 = static_cast<PARAM8 *>( params[ 7 ] );
PARAM9 *p9 = static_cast<PARAM9 *>( params[ 8 ] );
PARAM10 *p10 = static_cast<PARAM10 *>( params[ 9 ] );
PARAM11 *p11 = static_cast<PARAM11 *>( params[ 10 ] );
PARAM12 *p12 = static_cast<PARAM12 *>( params[ 11 ] );
PARAM13 *p13 = static_cast<PARAM13 *>( params[ 12 ] );
PARAM14 *p14 = static_cast<PARAM14 *>( params[ 13 ] );
PARAM15 *p15 = static_cast<PARAM15 *>( params[ 14 ] );
PARAM16 *p16 = static_cast<PARAM16 *>( params[ 15 ] );
PARAM17 *p17 = static_cast<PARAM17 *>( params[ 16 ] );
( static_cast<CLASSNAME *>( static_cast<CASTNAME *>( this ) )->*fn )( *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16, *p17 );
}
enum
{
DESTRUCT = 0xffff
};
};
#define CB(x, y) case (x): cb<CBCLASS>(&CBCLASS::y, retval, params); break;
#define CBT(x, y) case (x): cb<CBCLASST>(&CBCLASS::y, retval, params); break;
#define VCB(x, y) case (x): vcb<CBCLASS>(&CBCLASS::y, retval, params); break;
#define VCBT(x, y) case (x): vcb<CBCLASST>(&CBCLASS::y, retval, params); break;
#define RECVS_DISPATCH virtual int _dispatch(int msg, void *retval, void **params=0, int nparam=0)
#define START_DISPATCH \
int CBCLASS::_dispatch(int msg, void *retval, void **params, int nparam) { \
switch (msg) {
#define START_DISPATCH_INLINE \
int _dispatch(int msg, void *retval, void **params, int nparam) { \
switch (msg) {
//FINISH case DESTRUCT: delete this; return 1;
#define END_DISPATCH \
default: return 0; \
} \
return 1; \
}
#define FORWARD_DISPATCH(x) \
default: return x::_dispatch(msg, retval, params, nparam); \
} \
return 1; \
}
#define DISPATCH_CODES enum
inline int Dispatchable::AddRef()
{
return _call( Dispatchable::ADDREF, 0 );
}
inline int Dispatchable::Release()
{
return _call( Dispatchable::RELEASE, 0 );
}
inline int Dispatchable::QueryInterface( GUID interface_guid, void **object )
{
return _call( Dispatchable::QUERYINTERFACE, 0, interface_guid, object );
}
#ifndef DECLARE_EXTERNAL_SERVICE
#define DECLARE_EXTERNAL_SERVICE(_type, _name) extern _type *_name
#endif
#ifndef DEFINE_EXTERNAL_SERVICE
#define DEFINE_EXTERNAL_SERVICE(_type, _name) _type *_name=0
#endif

View File

@ -0,0 +1,60 @@
#include <precomp.h>
#include "convolve.h"
#define RED(a) (((a)>>16)&0xff)
#define GRN(a) (((a)>>8)&0xff)
#define BLU(a) (((a)&0xff))
#define ALP(a) (((a)>>24))
Convolve3x3::Convolve3x3(ARGB32 *_bits, int _w, int _h) : bits(_bits), w(_w), h(_h) {
ZERO(vals);
multiplier = 0;
}
void Convolve3x3::setPos(int x, int y, float v) {
ASSERT(x >= -1 && x <= 1 && y >= -1 && y <= 1);
vals[y+1][x+1] = v;
}
void Convolve3x3::setMultiplier(int m) {
multiplier = m;
}
void Convolve3x3::convolve() {
if (bits == NULL || w <= 0 || h <= 0) return; // nothin'
MemMatrix<ARGB32> temp(w, h, bits); // make a copy
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (ALP(temp(x, y))<=1) continue;
float ra=0, rg=0, rb=0;
for (int a = -1; a <= 1; a++) {
for (int b = -1; b <= 1; b++) {
int px = x + a, py = y + b;
if (px < 0 || px >= w || py < 0 || py >= h) continue;
ARGB32 c = temp(px, py);
if (ALP(c) <= 1) continue;
ra += (float)RED(c) * vals[b][a] * multiplier;
rg += (float)GRN(c) * vals[b][a] * multiplier;
rb += (float)BLU(c) * vals[b][a] * multiplier;
}
}
unsigned int r = MINMAX((int)ra, 0, 255);
unsigned int g = MINMAX((int)rg, 0, 255);
unsigned int b = MINMAX((int)rb, 0, 255);
unsigned int lum = MAX(MAX(r, g), b);
if (lum < 64) lum = 0;
else if (lum > 192) lum = 255;
//bits[x+y*w] = (ALP(*temp.m(x, y))<<24)|(r<<16)|(g<<8)|(b);
bits[x+y*w] &= 0xffffff;
bits[x+y*w] |= (255-lum) << 24;
//if (lum < 64) {
// bits[x+y*w] &= 0xffff00ff;
// bits[x+y*w] |= lum << 8;
//} else {
// bits[x+y*w] &= 0xff00ffff;
// bits[x+y*w] |= lum << 16;
//}
}
}
}

View File

@ -0,0 +1,24 @@
#ifndef _CONVOLVE_H
#define _CONVOLVE_H
#include "platform/types.h"
// world's slowest crappiest convolve :P think it sucks? write a better one
// and send it to me
class Convolve3x3 {
public:
Convolve3x3(ARGB32 *bits, int w, int h);
void setPos(int x, int y, float v);
void setMultiplier(int m);
void convolve();
private:
ARGB32 *bits;
int w, h;
float vals[3][3];
float multiplier;
};
#endif

View File

@ -0,0 +1,458 @@
#include <precomp.h>
#include "drawpoly.h"
#include <bfc/parse/pathparse.h>
#define MAXPOINTS 32
static ARGB32 *bits, color;
static int w, h, across;
struct Point2d {
int X, Y;
};
typedef struct Point2d Point2d; // bleh
static Point2d points[MAXPOINTS];
static int npoints;
void Draw::beginPolygon(ARGB32 *bits, int w, int h, ARGB32 color) {
::bits = bits;
::w = w;
::h = h;
::color = color;
::across = w;
npoints = 0;
}
void Draw::addPoint(int x, int y) {
if (npoints >= MAXPOINTS) return;
points[npoints].X = x;
points[npoints].Y = y;
npoints++;
}
static void premultiply(ARGB32 *m_pBits, int nwords) {
for (; nwords > 0; nwords--, m_pBits++) {
unsigned __int8 *pixel = (unsigned __int8 *)m_pBits;
unsigned int alpha = pixel[3];
if (alpha == 255) continue;
pixel[0] = (pixel[0] * alpha) >> 8; // blue
pixel[1] = (pixel[1] * alpha) >> 8; // green
pixel[2] = (pixel[2] * alpha) >> 8; // red
}
}
void Draw::drawPointList(ARGB32 *bits, int w, int h, const wchar_t *pointlist) {
if (pointlist == NULL || *pointlist == '\0') return;
PathParserW outer(pointlist, L"|");
const wchar_t *pl;
for (int i = 0; (pl = outer.enumString(i)) != NULL; i++)
{
PathParserW inner(pl, L"=");
ARGB32 color = WASABI_API_SKIN->parse(inner.enumStringSafe(1, L"255,255,255,255"), L"coloralpha");
int a = color & 0xff000000;
color = _byteswap_ulong(color<<8) | a;
premultiply(&color, 1);
beginPolygon(bits, w, h, color);
PathParserW eener(inner.enumStringSafe(0, L"0,0"), L";");
const wchar_t *cc;
for (int j = 0; (cc = eener.enumString(j)) != NULL; j++) {
PathParserW com(cc, L",");
const wchar_t *xs = com.enumStringSafe(0, L"0");
int x = wcschr(xs, '.') ? (int)floor(WTOF(xs) * w + .5f) : WTOI(xs);
const wchar_t *ys = com.enumStringSafe(1, L"0");
int y = wcschr(ys, '.') ? (int)floor(WTOF(ys) * h + .5f) : WTOI(ys);
addPoint(x, y);
}
endPolygon();
}
}
#define PIXEL ARGB32
// this originally came from Michael Abrash's Zen of Graphics Programming
// been modified a bit
/* DRAWPOLY.H: Header file for polygon-filling code */
/* Describes a single point (used for a single vertex) */
//struct Point2d {
// int X; /* X coordinate */
// int Y; /* Y coordinate */
//};
//typedef struct Point2d Point2d;
typedef struct {
int X, Y;
} Point2dC;
/* Describes a series of points (used to store a list of vertices that
describe a polygon; each vertex is assumed to connect to the two
adjacent vertices, and the last vertex is assumed to connect to the
first) */
struct Point2dListHeader {
int Length; /* # of points */
struct Point2d *Point2dPtr; /* pointer to list of points */
};
typedef struct Point2dListHeader Point2dListHeader;
/* Describes the beginning and ending X coordinates of a single
horizontal line */
struct HLine {
int XStart; /* X coordinate of leftmost pixel in line */
int XEnd; /* X coordinate of rightmost pixel in line */
};
typedef struct {
int XStart, XEnd;
} HLineColor;
/* Describes a Length-long series of horizontal lines, all assumed to
be on contiguous scan lines starting at YStart and proceeding
downward (used to describe a scan-converted polygon to the
low-level hardware-dependent drawing code) */
struct HLineList {
int Length; /* # of horizontal lines */
int YStart; /* Y coordinate of topmost line */
struct HLine * HLinePtr; /* pointer to list of horz lines */
};
static void DrawHorizontalLineList(struct HLineList * HLineListPtr, PIXEL *dest,
PIXEL Color) {
struct HLine *HLinePtr, *ptr;
int Length, Width, c;
PIXEL *ScreenPtr;
/* Point to the start of the first scan line on which to draw */
ScreenPtr = dest + HLineListPtr->YStart * across;
Length = HLineListPtr->Length;
/* Point to the XStart/XEnd descriptor for the first (top)
horizontal line */
HLinePtr = HLineListPtr->HLinePtr;
/* clip left/right */
for (ptr = HLinePtr, c = Length; c; c--) {
if (ptr->XStart < 0) ptr->XStart = 0;
if (ptr->XEnd >= w) ptr->XEnd = w - 1;
ptr++;
}
/* clip top */
if (HLineListPtr->YStart < 0) {
int skip = -HLineListPtr->YStart;
HLineListPtr->YStart = 0;
ScreenPtr += across * skip;
Length -= skip;
HLinePtr += skip;
}
/* clip bottom */
if (HLineListPtr->YStart + Length > h) {
Length -= (HLineListPtr->YStart + Length) - h;
}
/* Draw each horizontal line in turn, starting with the top one and
advancing one line each time */
while (Length-- > 0) {
/* Draw the whole horizontal line if it has a positive width */
if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0)
// bmemsetw(ScreenPtr+HLinePtr->XStart, Color, Width);
MEMFILL<PIXEL>(ScreenPtr+HLinePtr->XStart, Color, Width);
HLinePtr++; /* point to next scan line X info */
ScreenPtr += across; /* point to next scan line start */
}
}
/* Scan converts an edge from (X1,Y1) to (X2,Y2), not including the
point at (X2,Y2). If SkipFirst == 1, the point at (X1,Y1) isn't
drawn; if SkipFirst == 0, it is. For each scan line, the pixel
closest to the scanned edge without being to the left of the
scanned edge is chosen. Uses an all-integer approach for speed and
precision
Link with L21-1.C, L21-3.C, and L22-1.C in Compact model.
Tested with Borland C++ 4.02 by Jim Mischel 12/16/94.
*/
static void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
int SkipFirst, struct HLine **EdgePoint2dPtr) {
int DeltaX, Height, Width, AdvanceAmt, ErrorTerm, i;
int ErrorTermAdvance, XMajorAdvanceAmt;
struct HLine *WorkingEdgePoint2dPtr;
WorkingEdgePoint2dPtr = *EdgePoint2dPtr; /* avoid double dereference */
AdvanceAmt = ((DeltaX = X2 - X1) > 0) ? 1 : -1;
/* direction in which X moves (Y2 is
always > Y1, so Y always counts up) */
if ((Height = Y2 - Y1) <= 0) /* Y length of the edge */
return; /* guard against 0-length and horizontal edges */
/* Figure out whether the edge is vertical, diagonal, X-major
(mostly horizontal), or Y-major (mostly vertical) and handle
appropriately */
if ((Width = abs(DeltaX)) == 0) {
/* The edge is vertical; special-case by just storing the same
X coordinate for every scan line */
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePoint2dPtr->XStart = X1;
else
WorkingEdgePoint2dPtr->XEnd = X1;
}
} else if (Width == Height) {
/* The edge is diagonal; special-case by advancing the X
coordinate 1 pixel for each scan line */
if (SkipFirst) /* skip the first point if so indicated */
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePoint2dPtr->XStart = X1;
else
WorkingEdgePoint2dPtr->XEnd = X1;
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
}
} else if (Height > Width) {
/* Edge is closer to vertical than horizontal (Y-major) */
if (DeltaX >= 0)
ErrorTerm = 0; /* initial error term going left->right */
else
ErrorTerm = -Height + 1; /* going right->left */
if (SkipFirst) { /* skip the first point if so indicated */
/* Determine whether it's time for the X coord to advance */
if ((ErrorTerm += Width) > 0) {
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
ErrorTerm -= Height; /* advance ErrorTerm to next point */
}
}
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePoint2dPtr->XStart = X1;
else
WorkingEdgePoint2dPtr->XEnd = X1;
/* Determine whether it's time for the X coord to advance */
if ((ErrorTerm += Width) > 0) {
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
} else {
/* Edge is closer to horizontal than vertical (X-major) */
/* Minimum distance to advance X each time */
XMajorAdvanceAmt = (Width / Height) * AdvanceAmt;
/* Error term advance for deciding when to advance X 1 extra */
ErrorTermAdvance = Width % Height;
if (DeltaX >= 0)
ErrorTerm = 0; /* initial error term going left->right */
else
ErrorTerm = -Height + 1; /* going right->left */
if (SkipFirst) { /* skip the first point if so indicated */
X1 += XMajorAdvanceAmt; /* move X minimum distance */
/* Determine whether it's time for X to advance one extra */
if ((ErrorTerm += ErrorTermAdvance) > 0) {
X1 += AdvanceAmt; /* move X one more */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePoint2dPtr->XStart = X1;
else
WorkingEdgePoint2dPtr->XEnd = X1;
X1 += XMajorAdvanceAmt; /* move X minimum distance */
/* Determine whether it's time for X to advance one extra */
if ((ErrorTerm += ErrorTermAdvance) > 0) {
X1 += AdvanceAmt; /* move X one more */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
}
*EdgePoint2dPtr = WorkingEdgePoint2dPtr; /* advance caller's ptr */
}
/* Color-fills a convex polygon. All vertices are offset by (XOffset,
YOffset). "Convex" means that every horizontal line drawn through
the polygon at any point would cross exactly two active edges
(neither horizontal lines nor zero-length edges count as active
edges; both are acceptable anywhere in the polygon), and that the
right & left edges never cross. (It's OK for them to touch, though,
so long as the right edge never crosses over to the left of the
left edge.) Nonconvex polygons won't be drawn properly. Returns 1
for success, 0 if memory allocation failed.
Compiled with Borland C++ 4.02. Link with L21-3.C.
Checked by Jim Mischel 11/30/94.
*/
/* Advances the index by one vertex forward through the vertex list,
wrapping at the end of the list */
#define INDEX_FORWARD(Index) \
Index = (Index + 1) % VertexList->Length;
/* Advances the index by one vertex backward through the vertex list,
wrapping at the start of the list */
#define INDEX_BACKWARD(Index) \
Index = (Index - 1 + VertexList->Length) % VertexList->Length;
/* Advances the index by one vertex either forward or backward through
the vertex list, wrapping at either end of the list */
#define INDEX_MOVE(Index,Direction) \
if (Direction > 0) \
Index = (Index + 1) % VertexList->Length; \
else \
Index = (Index - 1 + VertexList->Length) % VertexList->Length;
int FillConvexPolygon(struct Point2dListHeader *VertexList, PIXEL *dest,
PIXEL Color) {
int i, MinIndexL, MaxIndex, MinIndexR, SkipFirst, Temp;
int MinPoint2d_Y, MaxPoint2d_Y, TopIsFlat, LeftEdgeDir;
int NextIndex, CurrentIndex, PreviousIndex;
int DeltaXN, DeltaYN, DeltaXP, DeltaYP;
struct HLineList WorkingHLineList;
struct HLine *EdgePoint2dPtr;
struct Point2d *VertexPtr;
/* Point to the vertex list */
VertexPtr = VertexList->Point2dPtr;
/* Scan the list to find the top and bottom of the polygon */
if (VertexList->Length == 0)
return(1); /* reject null polygons */
MaxPoint2d_Y = MinPoint2d_Y = VertexPtr[MinIndexL = MaxIndex = 0].Y;
for (i = 1; i < VertexList->Length; i++) {
if (VertexPtr[i].Y < MinPoint2d_Y)
MinPoint2d_Y = VertexPtr[MinIndexL = i].Y; /* new top */
else if (VertexPtr[i].Y > MaxPoint2d_Y)
MaxPoint2d_Y = VertexPtr[MaxIndex = i].Y; /* new bottom */
}
if (MinPoint2d_Y == MaxPoint2d_Y)
return(1); /* polygon is 0-height; avoid infinite loop below */
/* Scan in ascending order to find the last top-edge point */
MinIndexR = MinIndexL;
while (VertexPtr[MinIndexR].Y == MinPoint2d_Y)
INDEX_FORWARD(MinIndexR);
INDEX_BACKWARD(MinIndexR); /* back up to last top-edge point */
/* Now scan in descending order to find the first top-edge point */
while (VertexPtr[MinIndexL].Y == MinPoint2d_Y)
INDEX_BACKWARD(MinIndexL);
INDEX_FORWARD(MinIndexL); /* back up to first top-edge point */
/* Figure out which direction through the vertex list from the top
vertex is the left edge and which is the right */
LeftEdgeDir = -1; /* assume left edge runs down thru vertex list */
if ((TopIsFlat = (VertexPtr[MinIndexL].X !=
VertexPtr[MinIndexR].X) ? 1 : 0) == 1) {
/* If the top is flat, just see which of the ends is leftmost */
if (VertexPtr[MinIndexL].X > VertexPtr[MinIndexR].X) {
LeftEdgeDir = 1; /* left edge runs up through vertex list */
Temp = MinIndexL; /* swap the indices so MinIndexL */
MinIndexL = MinIndexR; /* points to the start of the left */
MinIndexR = Temp; /* edge, similarly for MinIndexR */
}
} else {
/* Point to the downward end of the first line of each of the
two edges down from the top */
NextIndex = MinIndexR;
INDEX_FORWARD(NextIndex);
PreviousIndex = MinIndexL;
INDEX_BACKWARD(PreviousIndex);
/* Calculate X and Y lengths from the top vertex to the end of
the first line down each edge; use those to compare slopes
and see which line is leftmost */
DeltaXN = VertexPtr[NextIndex].X - VertexPtr[MinIndexL].X;
DeltaYN = VertexPtr[NextIndex].Y - VertexPtr[MinIndexL].Y;
DeltaXP = VertexPtr[PreviousIndex].X - VertexPtr[MinIndexL].X;
DeltaYP = VertexPtr[PreviousIndex].Y - VertexPtr[MinIndexL].Y;
if (((long)DeltaXN * DeltaYP - (long)DeltaYN * DeltaXP) < 0L) {
LeftEdgeDir = 1; /* left edge runs up through vertex list */
Temp = MinIndexL; /* swap the indices so MinIndexL */
MinIndexL = MinIndexR; /* points to the start of the left */
MinIndexR = Temp; /* edge, similarly for MinIndexR */
}
}
/* Set the # of scan lines in the polygon, skipping the bottom edge
and also skipping the top vertex if the top isn't flat because
in that case the top vertex has a right edge component, and set
the top scan line to draw, which is likewise the second line of
the polygon unless the top is flat */
if ((WorkingHLineList.Length =
MaxPoint2d_Y - MinPoint2d_Y - 1 + TopIsFlat) <= 0)
return(1); /* there's nothing to draw, so we're done */
//WorkingHLineList.YStart = YOffset + MinPoint2d_Y + 1 - TopIsFlat;
WorkingHLineList.YStart = MinPoint2d_Y + 1 - TopIsFlat;
/* Get memory in which to store the line list we generate */
if ((WorkingHLineList.HLinePtr =
(struct HLine *) (malloc(sizeof(struct HLine) *
WorkingHLineList.Length))) == NULL)
return(0); /* couldn't get memory for the line list */
/* Scan the left edge and store the boundary points in the list */
/* Initial pointer for storing scan converted left-edge coords */
EdgePoint2dPtr = WorkingHLineList.HLinePtr;
/* Start from the top of the left edge */
PreviousIndex = CurrentIndex = MinIndexL;
/* Skip the first point of the first line unless the top is flat;
if the top isn't flat, the top vertex is exactly on a right
edge and isn't drawn */
SkipFirst = TopIsFlat ? 0 : 1;
/* Scan convert each line in the left edge from top to bottom */
do {
INDEX_MOVE(CurrentIndex,LeftEdgeDir);
ScanEdge(VertexPtr[PreviousIndex].X,
VertexPtr[PreviousIndex].Y,
VertexPtr[CurrentIndex].X,
VertexPtr[CurrentIndex].Y, 1, SkipFirst, &EdgePoint2dPtr);
PreviousIndex = CurrentIndex;
SkipFirst = 0; /* scan convert the first point from now on */
} while (CurrentIndex != MaxIndex);
/* Scan the right edge and store the boundary points in the list */
EdgePoint2dPtr = WorkingHLineList.HLinePtr;
PreviousIndex = CurrentIndex = MinIndexR;
SkipFirst = TopIsFlat ? 0 : 1;
/* Scan convert the right edge, top to bottom. X coordinates are
adjusted 1 to the left, effectively causing scan conversion of
the nearest points to the left of but not exactly on the edge */
do {
INDEX_MOVE(CurrentIndex,-LeftEdgeDir);
//ScanEdge(VertexPtr[PreviousIndex].X + XOffset - 1,
ScanEdge(VertexPtr[PreviousIndex].X - 1,
VertexPtr[PreviousIndex].Y,
//VertexPtr[CurrentIndex].X + XOffset - 1,
VertexPtr[CurrentIndex].X - 1,
VertexPtr[CurrentIndex].Y, 0, SkipFirst, &EdgePoint2dPtr);
PreviousIndex = CurrentIndex;
SkipFirst = 0; /* scan convert the first point from now on */
} while (CurrentIndex != MaxIndex);
/* Draw the line list representing the scan converted polygon */
//CUT (*drawfn)(&WorkingHLineList, dest, Color, vc);
DrawHorizontalLineList(&WorkingHLineList, dest, Color);
/* Release the line list's memory and we're successfully done */
free(WorkingHLineList.HLinePtr);
return(1);
}
// done with abrashitude
void Draw::endPolygon() {
if (npoints == 0) return;
struct Point2dListHeader head;
head.Length = npoints;
head.Point2dPtr = &points[0];
FillConvexPolygon(&head, bits, color);
}

View File

@ -0,0 +1,16 @@
#ifndef _DRAWPOLY_H
#define _DRAWPOLY_H
#include <bfc/wasabi_std.h>
class Draw {
public:
static void beginPolygon(ARGB32 *bits, int w, int h, ARGB32 color);
static void addPoint(int x, int y);
static void endPolygon();
static void drawPointList(ARGB32 *bits, int w, int h, const wchar_t *pointlist);
};
// x,y;x,y;x,y;x,y=R,G,B|x,y;x,y;x,y;=R,G,B
#endif

View File

@ -0,0 +1,309 @@
#include <precomp.h>
#include "gradient.h"
#include <math.h>//floor
#include <bfc/ptrlist.h>
#include <bfc/parse/pathparse.h>
#define DEFAULT_GRAD_MODE L"linear"
template<class T> inline void SWAP(T &a, T &b) {
T c = a;
a = b;
b = c;
}
inline unsigned int LERPu(unsigned int a, unsigned int b, double p) {
// ASSERT(p >= 0);
// ASSERT(p <= 1.f);
unsigned int ret = (unsigned int)((double)b * p + (double)a * (1. - p));
return ret;
}
inline float LERPf(double a, double b, float p) {
// ASSERT(p >= 0);
// ASSERT(p <= 1.f);
return (float)(b * p + a * (1. - p));
}
Gradient::Gradient() :
gammagroup(L"")
{
gradient_x1 = 0.0f;
gradient_y1 = 0.0f;
gradient_x2 = 1.0f;
gradient_y2 = 1.0f;
reverse_colors = 0;
antialias = 0;
mode = DEFAULT_GRAD_MODE;
list.addItem(new GradientPoint(0.0f, 0xff00ff00));
list.addItem(new GradientPoint(.5, 0x000000ff));
list.addItem(new GradientPoint(1.0f, 0xffff0000));
}
Gradient::~Gradient() {
list.deleteAll();
}
void Gradient::setX1(float x1) {
gradient_x1 = x1;
onParamChange();
}
void Gradient::setY1(float y1) {
gradient_y1 = y1;
onParamChange();
}
void Gradient::setX2(float x2) {
gradient_x2 = x2;
onParamChange();
}
void Gradient::setY2(float y2) {
gradient_y2 = y2;
onParamChange();
}
void Gradient::clearPoints() {
list.deleteAll();
onParamChange();
}
void Gradient::addPoint(float pos, ARGB32 color)
{
list.addItem(new GradientPoint(pos, color, gammagroup));
onParamChange();
}
void Gradient::setPoints(const wchar_t *pointlist)
{
clearPoints();
if (pointlist == NULL || *pointlist == '\0') return;
// 0.5=233,445,245,123;
PathParserW pp(pointlist, L";");
if (pp.getNumStrings() <= 0) return;
for (int i = 0; i < pp.getNumStrings(); i++)
{
PathParserW rp(pp.enumString(i), L"=");
if (rp.getNumStrings() != 2)
continue;
float pos = (float)WTOF(rp.enumString(0));
ARGB32 color = (ARGB32)WASABI_API_SKIN->parse(rp.enumString(1), L"coloralpha");
addPoint(pos, color);
}
}
void Gradient::setReverseColors(int c) {
reverse_colors = c;
}
void Gradient::setAntialias(int c) {
antialias = c;
}
void Gradient::setMode(const wchar_t *_mode) {
mode = _mode;
if (mode.isempty())
mode = DEFAULT_GRAD_MODE;
}
void Gradient::setGammaGroup(const wchar_t *group) {
gammagroup = group;
// reset our points
foreach(list)
list.getfor()->color.setColorGroup(group);
endfor
}
static inline ARGB32 colorLerp(ARGB32 color1, ARGB32 color2, double pos) {
unsigned int a1 = (color1>>24) & 0xff;
unsigned int a2 = (color2>>24) & 0xff;
unsigned int r1 = (color1>>16) & 0xff;
unsigned int r2 = (color2>>16) & 0xff;
unsigned int g1 = (color1>>8) & 0xff;
unsigned int g2 = (color2>>8) & 0xff;
unsigned int b1 = (color1) & 0xff;
unsigned int b2 = (color2) & 0xff;
return (LERPu(a1, a2, pos)<<24) | (LERPu(r1, r2, pos) << 16) | (LERPu(g1,g2,pos)<<8) | LERPu(b1, b2, pos);
}
void Gradient::renderGrad(ARGB32 *ptr, int len, int *positions) {
int npos = list.getNumItems();
ASSERT(npos >= 2);
ARGB32 color1, color2;
for (int i = 0; i < npos-1; i++) {
color1 = list.q(i)->color.getColor();
color2 = list.q(i+1)->color.getColor();
if (reverse_colors) {
color1 = BGRATOARGB(color1);
color2 = BGRATOARGB(color2);
}
int x1 = positions[i];
int x2 = positions[i+1];
if (x1 == x2) continue;
// hflip if need be
if (x1 > x2) {
SWAP(x1, x2);
SWAP(color1, color2);
}
float c = 0;
float segment_len = (float)((x2 - x1)+1);
if (x1 < 0) { // clip left
c += -x1;
x1 = 0;
}
for (int x = x1; x < x2; x++, c += 1.0f) {
if (x >= len) break; // clip right
ptr[x] = colorLerp(color1, color2, c / segment_len);
}
}
#if 0//later
// fill in left if needed
if (positions[0] > 0) MEMFILL<ARGB32>(ptr, list.q(0)->color, positions[0]);
// and right if needed
int rpos = positions[npos-1];
if (rpos < len) MEMFILL<ARGB32>(ptr+rpos, list.getLast()->color, len-rpos);
#endif
}
void Gradient::renderGradient(ARGB32 *bits, int w, int h, int pitch)
{
if (pitch == 0)
pitch = w;
list.sort();
ARGB32 default_color = 0xffff00ff;
if (list.getNumItems() == 1) default_color = list.q(0)->color.getColor();
// blank it out to start
if (pitch == w)
MEMFILL<ARGB32>(bits, default_color, w * h);
else
{
for (int i=0;i<h;i++)
MEMFILL<ARGB32>(bits+i*pitch, default_color, w);
}
if (list.getNumItems() > 1) {
if (mode.iscaseequal(L"linear")) {
//FUCKO: not if endcaps are filled
// force non-vertical lines
if (ABS(gradient_x1 - gradient_x2) < 0.0005f) gradient_x2 = gradient_x1+0.0005f;
double px1 = gradient_x1 * w, py1 = gradient_y1 * h;
double px2 = gradient_x2 * w, py2 = gradient_y2 * h;
// convert to y = mx + b
double m = (py2 - py1)/(px2 - px1);
m = -1.f/m; // invert the slope
int nitems = list.getNumItems();
// get the in-pixels x and y for points on the gradient
for (int i = 0; i < nitems; i++) {
GradientPoint *gp = list.q(i);
// need x and y given pos
gp->x = LERPf(px1, px2, gp->pos);
gp->y = LERPf(py1, py2, gp->pos);
}
MemBlock<int> positions(nitems);
for (int _y = 0; _y < h; _y++) {
// project all the color points onto this scanline
for (int i = 0; i < nitems; i++) {
GradientPoint *gp = list.q(i);
// y = mx + b
// b = y - mx;
double newb = gp->y - m * gp->x;
// y = mx + newb
// y - newb = mx
// (y - newb)/m = x
double xxx = (_y - newb)/m;
positions[i] = (int)floor(xxx+0.5f);
}
renderGrad(bits+_y*pitch, w, positions);
}
} else if (mode.iscaseequal(L"circular")) {
double tot = SQRT(SQR(gradient_x1 - gradient_x2) + SQR(gradient_y1 - gradient_y2));
foreach(list)
GradientPoint *gp = list.getfor();
gp->dist = gp->pos * tot;
endfor
ARGB32 *dst = bits;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
ARGB32 c;
if (antialias) {
double fx = (((double)x)-0.5f) / (double)w;
double fy = (((double)y)-0.5f) / (double)h;
ARGB32 ul = getPixelCirc(fx, fy);
fx = (((double)x)+0.5f) / (double)w;
fy = (((double)y)-0.5f) / (double)h;
ARGB32 ur = getPixelCirc(fx, fy);
fx = (((double)x)+0.5f) / (double)w;
fy = (((double)y)+0.5f) / (double)h;
ARGB32 lr = getPixelCirc(fx, fy);
fx = (((double)x)-0.5f) / (double)w;
fy = (((double)y)+0.5f) / (double)h;
ARGB32 ll = getPixelCirc(fx, fy);
c = colorLerp(colorLerp(ll, lr, 0.5f), colorLerp(ul, ur, 0.5f), 0.5);
} else {
double fy = (double)y / (double)h;
double fx = (double)x / (double)w;
c = getPixelCirc(fx, fy);
}
*dst++ = c;
}
dst += (pitch-w);
}
}
}//list.getNumItems()>1
if (pitch == w)
premultiplyARGB32(bits, w * h);
else
{
for (int i=0;i<h;i++)
premultiplyARGB32(bits+i*pitch, w);
}
}
ARGB32 Gradient::getPixelCirc(double fx, double fy) {
int nitems = list.getNumItems();
//double dist = SQR(fx - gradient_x1) + SQR(fy - gradient_y1);
double dist = SQRT(SQR(fx - gradient_x1) + SQR(fy - gradient_y1));
ARGB32 c = 0xff00ff00;
if (dist <= list.q(0)->dist)
c = list.q(0)->color.getColor();
else if (dist >= list.getLast()->dist)
c = list.getLast()->color.getColor();
else for (int i = 0; i < nitems-1; i++) {
if (list.q(i)->dist <= dist && list.q(i+1)->dist >= dist) {
double pdist = list.q(i+1)->dist - list.q(i)->dist;
double pp = dist - list.q(i)->dist;
pp /= pdist;
if (list.q(i)->color.getColor() == list.q(i+1)->color.getColor())
c = list.q(i)->color.getColor();
else
c = colorLerp(list.q(i)->color.getColor(), list.q(i+1)->color.getColor(), pp);
break;
}
}
if (reverse_colors) c = BGRATOARGB(c);
return c;
}

View File

@ -0,0 +1,67 @@
#ifndef _GRADIENT_H
#define _GRADIENT_H
#include <bfc/wasabi_std.h>
#include <bfc/string/StringW.h>
#include <tataki/color/filteredcolor.h>
class GradientPoint
{
public:
GradientPoint(float p, ARGB32 c, const wchar_t *group=L"") : pos(p), dist(0), color(c, group), x(0), y(0) { }
float pos;
double dist;
FilteredColor color;
float x, y;
static int compareItem(GradientPoint *p1, GradientPoint* p2) {
int r = CMP3(p1->pos, p2->pos);
if (r == 0) return CMP3(p1, p2);
else return r;
}
};
class Gradient
{
public:
Gradient();
virtual ~Gradient();
void setX1(float x1);
void setY1(float y1);
void setX2(float x2);
void setY2(float y2);
void clearPoints();
void addPoint(float pos, ARGB32 color);
// "pos=color;pos=color" "0.25=34,45,111"
void setPoints(const wchar_t *str);
void setReverseColors(int c);
void setAntialias(int c);
void setMode(const wchar_t *mode);
void setGammaGroup(const wchar_t *group);
// note: this will automatically premultiply against alpha
void renderGradient(ARGB32 *bits, int width, int height, int pitch=0);
protected:
virtual void onParamChange() { }
ARGB32 getPixelCirc(double x, double y);
private:
float gradient_x1, gradient_y1, gradient_x2, gradient_y2;
class GradientList : public PtrListQuickSorted<GradientPoint, GradientPoint> { };
GradientList list;
void renderGrad(ARGB32 *bits, int len, int *positions);
int reverse_colors;
int antialias;
StringW mode, gammagroup;
};
#endif

View File

@ -0,0 +1,17 @@
#include <precomp.h>
#include "skinfilter.h"
#include <studio/services/svc_skinfilter.h>
void ApplySkinFilters::apply(const char *elementid, const char *forced_gammagroup, ARGB32 *bits, int w, int h, int bpp) {
if ((elementid == NULL && forced_gammagroup == NULL) || bits == NULL || w <= 0 || h <= 0) return;
SkinFilterEnum sfe;
while (1) {
svc_skinFilter *obj = sfe.getNext(FALSE);
if (!obj) break;
obj->filterBitmap((unsigned char *)bits, w, h, bpp, elementid, forced_gammagroup);
sfe.getLastFactory()->releaseInterface(obj);
}
}

View File

@ -0,0 +1,11 @@
#ifndef _SKINFILTER_H
#define _SKINFILTER_H
#include <bfc/std.h>
class ApplySkinFilters {
public:
static void apply(const char *element_id, const char *forced_gammagroup, ARGB32 *bits, int w, int h, int bpp=32);
};
#endif

6
Src/Wasabi/bfc/error.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#ifndef REPLICANT_INCLUDE
#include "../../replicant/foundation/error.h"
#else
#include "foundation/error.h"
#endif

View File

@ -0,0 +1,2 @@
#include "precomp_wasabi_bfc.h"
#include "filename.h"

View File

@ -0,0 +1,26 @@
#ifndef _FILENAME_H
#define _FILENAME_H
#include <bfc/string/StringW.h>
#include <bfc/string/playstring.h>
#include <bfc/dispatch.h>
// a simple class to drag-and-drop filenames around
#define DD_FILENAME L"DD_Filename v1"
// another implementation that uses the central playstring table
class FilenamePS : private Playstring
{
public:
FilenamePS(const wchar_t *str) : Playstring(str) {}
const wchar_t *getFilename() { return getValue(); }
operator const wchar_t *() { return getFilename(); }
static const wchar_t *dragitem_getDatatype() { return DD_FILENAME; }
protected:
FilenamePS(const FilenamePS &fn) {}
FilenamePS& operator =(const FilenamePS &ps) { return *this; }
};
#endif

View File

@ -0,0 +1,129 @@
#include "precomp_wasabi_bfc.h"
#include "readdir.h"
#ifdef _WIN32
#include <shlwapi.h>
#endif
#if !defined(WIN32) && !defined(LINUX)
#error port me
#endif
//PORT
ReadDir::ReadDir( const wchar_t *_path, const wchar_t *_match, bool _skipdots ) : skipdots( _skipdots ), first( 1 ), path( _path ), match( _match )
{
files = INVALID_HANDLE_VALUE;
if ( match.isempty() )
match = MATCHALLFILES;
ZERO( data );
}
ReadDir::~ReadDir()
{
//PORT
#ifdef WIN32
if ( files != INVALID_HANDLE_VALUE ) FindClose( files );
#endif
#ifdef LINUX
if ( d != NULL ) closedir( d );
#endif
}
int ReadDir::next()
{
//PORT
#ifdef WIN32
for ( ;;)
{
if ( first )
{
wchar_t fullpath[ MAX_PATH ];
PathCombineW( fullpath, path.getValue(), match.getValue() );
files = FindFirstFileW( fullpath, &data );
}
if ( files == INVALID_HANDLE_VALUE ) return 0;
if ( first )
{
first = 0;
if ( skipdots && ( isDotDir() || isDotDotDir() ) ) continue;
return 1;
}
if ( !FindNextFileW( files, &data ) ) return 0;
if ( skipdots && ( isDotDir() || isDotDotDir() ) ) continue;
return 1;
}
#endif//WIN32
#ifdef LINUX
path.AddBackslash();
if ( first || d == NULL )
{
if ( !( d = opendir( path ) ) ) return 0;
first = 0;
}
while ( 1 )
{
de = readdir( d );
if ( !de )
{
closedir( d );
d = NULL;
return 0;
}
StringW full;
full.printf( L"%s%s", path.v(), de->d_name );
if ( stat( full, &st ) == -1 )
continue;
if ( skipdots && ( isDotDir() || isDotDotDir() ) ) continue;
if ( !Std::match( match, de->d_name ) ) continue;
return 1;
}
#endif
}
const wchar_t *ReadDir::getFilename()
{
if ( first ) if ( !next() ) return NULL;
//PORT
return data.cFileName;
}
int ReadDir::isDir()
{
//PORT
if ( files == INVALID_HANDLE_VALUE ) return 0;
return !!( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY );
}
int ReadDir::isReadonly()
{
//PORT
if ( files == INVALID_HANDLE_VALUE ) return 0;
return !!( data.dwFileAttributes & FILE_ATTRIBUTE_READONLY );
}
int ReadDir::isDotDir()
{
//PORT
if ( files == INVALID_HANDLE_VALUE ) return 0;
return ( data.cFileName[ 0 ] == '.' && data.cFileName[ 1 ] == 0 );
}
int ReadDir::isDotDotDir()
{
//PORT
if ( files == INVALID_HANDLE_VALUE ) return 0;
return ( data.cFileName[ 0 ] == '.' && data.cFileName[ 1 ] == '.' && data.cFileName[ 2 ] == 0 );
}

View File

@ -0,0 +1,48 @@
#ifndef _READDIR_H
#define _READDIR_H
#include <bfc/common.h>
#include <bfc/string/StringW.h>
/* intended use:
ReadDir dir(path);
while (dir.next()) {
const char *fn = dir.getFilename();
}
*/
class ReadDir
{
public:
ReadDir(const wchar_t *path, const wchar_t *match=NULL, bool skipdots=true);
~ReadDir();
int next(); // done when returns 0
const wchar_t *getFilename();
int isDir(); // if current file is a dir
int isReadonly(); // if current file is readonly
int isDotDir(); // if given dir iteself is being enumerated (usually ".")
int isDotDotDir(); // if parent dir of cur dir is showing (usually "..")
const wchar_t *getPath() { return path; }
private:
StringW path, match;
int skipdots, first;
//PORT
#ifdef WIN32
HANDLE files;
WIN32_FIND_DATAW data; // (shrug) so we have two? so what?
//StringW filename;
#endif
#ifdef LINUX
DIR *d;
struct dirent *de;
struct stat st;
#endif
};
#endif

View File

@ -0,0 +1,67 @@
#include "precomp_wasabi_bfc.h"
#include "recursedir.h"
RecurseDir::RecurseDir( const wchar_t *_path, const wchar_t *_match ) :
path( _path ), match( _match )
{
if ( match.isempty() ) match = Wasabi::Std::matchAllFiles();
curdir = new ReadDir( path, match );
}
RecurseDir::~RecurseDir()
{
dirstack.deleteAll();
}
int RecurseDir::next()
{
for ( ;;)
{
if ( curdir == NULL )
{ // pop one off the stack
curdir = dirstack.getLast();
if ( curdir == NULL ) return 0; // done
dirstack.removeLastItem();
}
int r = curdir->next();
if ( r <= 0 )
{
delete curdir; curdir = NULL;
continue; // get another one
}
// ok, we have a file to look at
if ( curdir->isDir() )
{ // descend into it
StringW newpath = curdir->getPath();
newpath.AppendPath( curdir->getFilename() );
dirstack.addItem( curdir ); // push the old one
curdir = new ReadDir( newpath, match ); // start new one
continue;
}
return r;
}
}
const wchar_t *RecurseDir::getPath()
{
if ( curdir == NULL )
return NULL;
return curdir->getPath();
}
const wchar_t *RecurseDir::getFilename()
{
if ( curdir == NULL )
return NULL;
return curdir->getFilename();
}
const wchar_t *RecurseDir::getOriginalPath()
{
return path;
}

View File

@ -0,0 +1,73 @@
#ifndef _RECURSEDIR_H
#define _RECURSEDIR_H
#include <bfc/wasabi_std.h>
#include <bfc/ptrlist.h>
#include <bfc/common.h>
#include <bfc/file/readdir.h>
class ReadDir;
/**
Read the contents of a directory, recursively.
Also possible to use search match patterns.
@short Recursive directory reading.
@author Nullsoft
@ver 1.0
@see ReadDir
*/
class RecurseDir {
public:
/**
Sets the directory to read and the match pattern.
If no match pattern is set, it will match against
all files.
@param path The path of the directory to read.
@param match The match pattern to use.
*/
RecurseDir(const wchar_t *path, const wchar_t *match=NULL);
/**
Deletes the directory stack.
*/
~RecurseDir();
/**
Advance to the next file.
@ret 0, No more files to read; > 0, Files left to read.
*/
int next();
/**
Restart from the top of the directory tree.
@ret 0
*/
int restart();
/**
Get the current directory path.
@ret The path.
*/
const wchar_t *getPath();
/**
Get the filename for the current file.
@ret The filename.
*/
const wchar_t *getFilename();
const wchar_t *getOriginalPath();
private:
StringW path, match;
ReadDir *curdir;
PtrList<ReadDir> dirstack;
};
#endif

View File

@ -0,0 +1,213 @@
/*
* Copyright 2000 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// 03/29/2004, f. gastellu : added _makepath and _wmakepath
#include "splitpath.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WANT_UNICODE
void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext)
{
const WCHAR* end; /* end of processed string */
const WCHAR* p; /* search pointer */
const WCHAR* s; /* copy pointer */
/* extract drive name */
if (path[0] && path[1]==':') {
if (drv) {
*drv++ = *path++;
*drv++ = *path++;
*drv = L'\0';
}
} else if (drv)
*drv = L'\0';
/* search for end of string or stream separator */
for(end=path; *end && *end!=L':'; )
end++;
/* search for begin of file extension */
for(p=end; p>path && *--p!=L'\\' && *p!=L'/'; )
if (*p == L'.') {
end = p;
break;
}
if (ext)
for(s=end; *ext=*s++; )
ext++;
/* search for end of directory name */
for(p=end; p>path; )
if (*--p=='\\' || *p=='/') {
p++;
break;
}
if (name) {
for(s=p; s<end; )
*name++ = *s++;
*name = L'\0';
}
if (dir) {
for(s=path; s<p; )
*dir++ = *s++;
*dir = L'\0';
}
}
#endif
#ifdef WANT_ACP
void _splitpath(const char* path, char* drv, char* dir, char* name, char* ext)
{
const char* end; /* end of processed string */
const char* p; /* search pointer */
const char* s; /* copy pointer */
/* extract drive name */
if (path[0] && path[1]==':') {
if (drv) {
*drv++ = *path++;
*drv++ = *path++;
*drv = '\0';
}
} else if (drv)
*drv = '\0';
/* search for end of string or stream separator */
for(end=path; *end && *end!=':'; )
end++;
/* search for begin of file extension */
for(p=end; p>path && *--p!='\\' && *p!='/'; )
if (*p == '.') {
end = p;
break;
}
if (ext)
for(s=end; (*ext=*s++); )
ext++;
/* search for end of directory name */
for(p=end; p>path; )
if (*--p=='\\' || *p=='/') {
p++;
break;
}
if (name) {
for(s=p; s<end; )
*name++ = *s++;
*name = '\0';
}
if (dir) {
for(s=path; s<p; )
*dir++ = *s++;
*dir = '\0';
}
}
#endif
#ifdef WANT_UNICODE
void _wmakepath( WCHAR *path, const WCHAR *drive, const WCHAR *dir, const WCHAR *fname, const WCHAR *ext ) {
if (!path) return;
*path = 0;
if (drive) {
*path++ = *drive;
*path++ = ':';
}
if (dir) {
strcat(path, dir);
if (dir[strlen(dir)-1] != '\\' && dir[strlen(dir)-1] != '/')
strcat(path, "/");
path += strlen(path);
}
if (fname) strcat(path, fname);
if (ext) {
if (*ext != '.') strcat(path++, ".");
strcat(path, ext);
}
}
#endif
#ifdef WANT_ACP
void _makepath( char *path, const char *drive, const char *dir, const char *fname, const char *ext ) {
if (!path) return;
*path = 0;
if (drive) {
*path++ = *drive;
*path++ = ':';
}
if (dir) {
strcat(path, dir);
if (dir[strlen(dir)-1] != '\\' && dir[strlen(dir)-1] != '/')
strcat(path, "/");
path += strlen(path);
}
if (fname) strcat(path, fname);
if (ext) {
if (*ext != '.') strcat(path++, ".");
strcat(path, ext);
}
}
#endif
/*
void main() // test splipath()
{
TCHAR drv[_MAX_DRIVE+1], dir[_MAX_DIR], name[_MAX_FNAME], ext[_MAX_EXT];
_tsplitpath(L"x\\y", drv, dir, name, ext);
_tsplitpath(L"x\\", drv, dir, name, ext);
_tsplitpath(L"\\x", drv, dir, name, ext);
_tsplitpath(L"x", drv, dir, name, ext);
_tsplitpath(L"", drv, dir, name, ext);
_tsplitpath(L".x", drv, dir, name, ext);
_tsplitpath(L":x", drv, dir, name, ext);
_tsplitpath(L"a:x", drv, dir, name, ext);
_tsplitpath(L"a.b:x", drv, dir, name, ext);
_tsplitpath(L"W:\\/\\abc/Z:~", drv, dir, name, ext);
_tsplitpath(L"abc.EFGH:12345", drv, dir, name, ext);
_tsplitpath(L"C:/dos/command.com", drv, dir, name, ext);
}
*/
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,26 @@
#ifndef _SPLITPATH_H
#define _SPLITPATH_H
#ifndef _WIN32
#ifdef __cplusplus
extern "C" {
#endif
//#define WANT_UNICODE
#define WANT_ACP
#ifdef WANT_UNICODE
void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
void _wmakepath( WCHAR *path, const WCHAR *drive, const WCHAR *dir, const WCHAR *fname, const WCHAR *ext );
#endif
#ifdef WANT_ACP
void _splitpath(const char* path, char* drv, char* dir, char* name, char* ext);
void _makepath( char *path, const char *drive, const char *dir, const char *fname, const char *ext);
#endif
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,18 @@
#ifndef _TMPNAMESTR_H
#define _TMPNAMESTR_H
#include <bfc/string/StringW.h>
class TmpNameStrW : public StringW
{
public:
TmpNameStrW()
{
wchar_t tmp[WA_MAX_PATH]=L"";
TMPNAM(tmp);
setValue(tmp);
}
};
#endif

View File

@ -0,0 +1,64 @@
// NONPORTABLE NONPORTABLE NONPORTABLE
#include "precomp_wasabi_bfc.h"
#ifdef WIN32
#include <windows.h>
#endif
#include "wildcharsenum.h"
#include <bfc/parse/pathparse.h>
#include <bfc/parse/paramparser.h>
#include <bfc/file/readdir.h>
WildcharsEnumerator::WildcharsEnumerator(const wchar_t *_selection) : selection(_selection)
{
// Then scan.
rescan();
}
WildcharsEnumerator::~WildcharsEnumerator() {
finddatalist.deleteAll();
}
int WildcharsEnumerator::getNumFiles()
{
return finddatalist.getNumItems();
}
const wchar_t *WildcharsEnumerator::enumFile(int n) {
StringW path = finddatalist.enumItem(n)->path;
if (!path.isempty())
{
enumFileString = StringPathCombine(path.getValue(), finddatalist.enumItem(n)->filename.getValue());
return enumFileString;
}
return finddatalist.enumItem(n)->filename;
}
void WildcharsEnumerator::rescan()
{
finddatalist.removeAll();
ParamParser pp(selection, L";");
for (int is = 0; is < pp.getNumItems(); is++)
{
StringW _selection = pp.enumItem(is);
PathParserW parse(_selection);
StringW path = L"";
StringW mask = L"";
for (int i=0;i<parse.getNumStrings()-1;i++)
path.AppendFolder(parse.enumString(i));
mask = parse.getLastString();
// enum files and store a list
ReadDir rd(path, mask, true);
while (rd.next()) {
finddatalist.addItem(new find_entry(rd.getPath(), rd.getFilename()));
}
}
}
int WildcharsEnumerator::isWildchars(const wchar_t *filename)
{
return (wcschr(filename, '*') || wcschr(filename, '?'));
}

View File

@ -0,0 +1,34 @@
#ifndef __WILDCHARSENUM_H
#define __WILDCHARSENUM_H
#include <bfc/ptrlist.h>
#include <bfc/string/StringW.h>
class find_entry {
public:
find_entry(const wchar_t *_path, const wchar_t *_filename) : path(_path), filename(_filename) {}
~find_entry() {}
StringW path;
StringW filename;
};
class WildcharsEnumerator
{
public:
WildcharsEnumerator(const wchar_t *_selection);
virtual ~WildcharsEnumerator();
int getNumFiles();
const wchar_t *enumFile(int n);
void rescan();
static int isWildchars(const wchar_t *filename);
private:
StringW selection;
PtrList <find_entry> finddatalist;
StringW singfiledup;
StringW enumFileString;
};
#endif

View File

@ -0,0 +1,22 @@
#include "foreach.h"
__foreach::__foreach(const PtrListRoot &ptrlist, int reverse) :
list(ptrlist.getNumItems(), ptrlist.getItemList()), pos(0)
{
if (reverse) list.reverse();
}
__foreach::__foreach(const PtrListRoot *ptrlist, int reverse) :
list(ptrlist->getNumItems(), ptrlist->getItemList()), pos(0) {
if (reverse) list.reverse();
}
int __foreach::done() const { return (pos >= list.getSize()); }
void *__foreach::next(int advance) { if (advance) pos++; return getPtr(); }
void *__foreach::getPtr() const { return (pos < list.getSize()) ? list[pos] : NULL; }
int __foreach::getPos() const { return pos; }

55
Src/Wasabi/bfc/foreach.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef _FOREACH_H
#define _FOREACH_H
#include "memblock.h"
#include "ptrlist.h"
// foreach stuff
/* use like this:
PtrList<blah> list;
foreach(list)
list.getfor()->booga();
something(list.getfor());
endfor
*/
// foreach stuff
class __foreach
{
public:
__foreach(const PtrListRoot &ptrlist, int reverse=FALSE);
__foreach(const PtrListRoot *ptrlist, int reverse=FALSE);
int done() const;
void *next(int advance = TRUE);
void *getPtr() const;
int getPos() const;
private:
MemBlock<void *> list;
int pos;
};
#define foreach(x) \
{ \
void *__fe_void; \
__foreach ___f(x); \
for (__fe_void = ___f.getPtr(); !___f.done(); __fe_void = ___f.next()) {
#define getfor() castFor(__fe_void)
#define endfor \
} \
}
#define foreach_reverse(x) \
{ \
void *__fe_void; \
__foreach ___f(x, TRUE); \
for (__fe_void = ___f.getPtr(); !___f.done(); __fe_void = ___f.next()) {
#define getfor() castFor(__fe_void)
#define endfor \
} \
}
#define foreach_index (___f.getPos())
#endif

View File

@ -0,0 +1,81 @@
#include "precomp_wasabi_bfc.h"
#include "freelist.h"
// define this to turn off freelist behavior
//#define FREELIST_FUCT
FreelistPriv::FreelistPriv() {
total_allocated = 0;
}
FreelistPriv::~FreelistPriv() {
#ifdef ASSERTS_ENABLED
// ASSERTPR(total_allocated == 0, "didn't free entire freelist!(1)");
// ASSERTPR(blocks.getNumItems() == 0, "didn't free entire freelist!(2)");
if (total_allocated != 0) DebugStringW(L"didn't free entire freelist!(1)\n");
if (blocks.getNumItems() != 0) DebugStringW(L"didn't free entire freelist!(2)\n");
#endif
}
void *FreelistPriv::getRecord(int typesize, int blocksize, int initialblocksize) {
#ifdef FREELIST_FUCT
return MALLOC(typesize);
#else
ASSERT(typesize >= sizeof(void *));
FLMemBlock *mem = NULL;
for (int i = 0; i < blocks.getNumItems(); i++) {
mem = blocks[i];
if (mem->freelist != NULL) break;
mem = NULL;
}
if (mem == NULL) {
// figure record count for this new block
int siz = (blocks.getNumItems() ? blocksize : initialblocksize);
// allocate another block of memory
mem = new FLMemBlock(siz*typesize);
// prelink it into a freelist
char *record = static_cast<char *>(mem->freelist);
void **ptr;
for (int i = 0; i < siz-1; i++) {
ptr = reinterpret_cast<void **>(record);
record += typesize;
*ptr = static_cast<void *>(record);
}
// terminate newly made freelist
ptr = reinterpret_cast<void **>(record);
*ptr = NULL;
blocks.addItem(mem);
}
// get first free record
void *ret = mem->freelist;
// advance freelist *
mem->freelist = *(static_cast<void **>(mem->freelist));
mem->nallocated++;
total_allocated++;
return ret;
#endif
}
void FreelistPriv::freeRecord(void *record) {
#ifdef FREELIST_FUCT
FREE(record);
#else
FLMemBlock *mem=NULL;
for (int i = 0; i < blocks.getNumItems(); i++) {
mem = blocks[i];
if (mem->isMine(reinterpret_cast<MBT*>(record))) break;
mem = NULL;
}
ASSERTPR(mem != NULL, "attempted to free record with no block");
// stash it back on the block's freelist
*reinterpret_cast<void **>(record) = mem->freelist;
mem->freelist = record;
ASSERT(mem->nallocated > 0);
mem->nallocated--;
if (mem->nallocated == 0) {
blocks.delItem(mem);
}
total_allocated--;
#endif
}

93
Src/Wasabi/bfc/freelist.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef _FREELIST_H
#define _FREELIST_H
#include <bfc/wasabi_std.h>
#include <bfc/memblock.h>
#include <bfc/ptrlist.h>
// actual implementation
class FreelistPriv {
protected:
FreelistPriv();
~FreelistPriv();
void *getRecord(int typesize, int blocksize, int initialblocksize);
void freeRecord(void *rec);
private:
int total_allocated;
typedef uint8_t MBT;
class FLMemBlock : public MemBlock<MBT> {
public:
FLMemBlock(int siz) : MemBlock<MBT>(siz) {
freelist = getMemory();
nallocated = 0;
}
void *freelist;
int nallocated; // # of records assigned from block
};
PtrList< FLMemBlock > blocks; // the blocks of mem we alloc from
};
// type-safe template
static const int DEF_BLOCKSIZE=250;
template
<class T, int BLOCKSIZE=DEF_BLOCKSIZE, int INITIALBLOCKSIZE=DEF_BLOCKSIZE, int ALIGNMENT=4>
class Freelist : private FreelistPriv {
public:
// just returns the memory, you have to call constructor manually
T *getRecord() {
return static_cast<T *>(FreelistPriv::getRecord(itemsize(), BLOCKSIZE, INITIALBLOCKSIZE));
}
// creates object via default constructor
T *newRecord() {
T *ret = getRecord();
#ifdef FORTIFY
#undef new
#endif
new(ret) T;
#ifdef FORTIFY
#define new ZFortify_New
#endif
return ret;
}
// creates object via 1-parameter constructor
template<class P1>
T *newRecord(P1 p1) {
T *ret = getRecord();
#ifdef FORTIFY
#undef new
#endif
new(ret) T(p1);
#ifdef FORTIFY
#define new ZFortify_New
#endif
return ret;
}
// just frees it, you have to call destructor manually
void freeRecord(T *record) { FreelistPriv::freeRecord(record); }
// calls delete for you, and frees it
void deleteRecord(T *record) {
if (record != NULL) {
record->~T();
freeRecord(record);
}
}
void deletePtrList(PtrList<T> *list) {
ASSERT(list != NULL);
for (int i = 0; i < list->getNumItems(); i++) {
deleteRecord(list->enumItem(i));
}
list->removeAll();
}
protected:
int itemsize() { return (sizeof(T) + (ALIGNMENT-1)) - (sizeof(T) % ALIGNMENT); }
};
#endif

View File

@ -0,0 +1,85 @@
#include "precomp_wasabi_bfc.h"
#include "loadlib.h"
#if !defined(WIN32) && !defined(LINUX)
#error port me
#endif
Library::Library(const wchar_t *filename) : NamedW(filename)
{
lib = NULL;
}
Library::~Library()
{
unload();
}
int Library::load(const wchar_t *newname)
{
if (lib != NULL && newname == NULL)
return 1;
unload();
if (newname != NULL)
setName(newname);
const wchar_t *n = getName();
ASSERT(n != NULL);
#ifdef WIN32
__try {
lib = LoadLibraryW(n);
} __except(EXCEPTION_EXECUTE_HANDLER)
{
// stupid DLL
lib = NULL;
OutputDebugString(L"exception while loading dll");
OutputDebugStringW(newname);
OutputDebugString(L"\n");
}
#elif defined(LINUX)
// Not using string to try to not use common/wasabi in Studio.exe
char *conv = _strdup( getName() );
int len = strlen( conv );
if ( ! strcasecmp( conv + len - 4, ".dll" ) )
{
strcpy( conv + len - 4, ".so" );
}
lib = dlopen(conv, RTLD_LAZY);
free( conv );
#else
#error port me!
#endif
if (lib == NULL) return 0;
return 1;
}
void Library::unload()
{
if (lib != NULL)
{
#ifdef WIN32
FreeLibrary(lib);
#elif defined(LINUX)
dlclose(lib);
#else
#error port me!
#endif
}
lib = NULL;
}
void *Library::getProcAddress(const char *procname)
{
ASSERT(procname != NULL);
#if defined(WIN32)
return GetProcAddress(lib, procname);
#elif defined(LINUX)
return dlsym(lib, procname);
#else
#error port me!
#endif
}

35
Src/Wasabi/bfc/loadlib.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef _LOADLIB_H
#define _LOADLIB_H
#include <bfc/wasabi_std.h>
#include <bfc/named.h>
class Library : public NamedW
{
public:
Library(const wchar_t *filename=NULL);
Library(const Library &l) {
lib = NULL; // FG> overrides default constructor, so we need to init this too...
load(l.getName());
}
~Library();
Library& operator =(const Library &l) {
if (this != &l) {
unload();
load(l.getName());
}
return *this;
}
int load(const wchar_t *filename=NULL);
void unload();
void *getProcAddress(const char *procname);
OSMODULEHANDLE getHandle() const { return lib; }
private:
OSMODULEHANDLE lib;
};
#endif

View File

@ -0,0 +1,66 @@
#include "memblock.h"
#include <bfc/bfc_assert.h>
#ifdef _DEBUG
int memblocks_totalsize=0;
#endif
VoidMemBlock::VoidMemBlock(int _size, const void *data) {
mem = NULL;
size = 0;
setSize(_size);
if (data != NULL && size > 0) MEMCPY(mem, data, size);
}
VoidMemBlock::~VoidMemBlock() {
#ifdef _DEBUG
memblocks_totalsize -= size;
#endif
FREE(mem);
}
void *VoidMemBlock::setSize(int newsize) {
#ifdef _DEBUG
memblocks_totalsize -= size;
#endif
ASSERT(newsize >= 0);
if (newsize < 0) newsize = 0;
if (newsize == 0) {
FREE(mem);
mem = NULL;
} else if (size != newsize) {
mem = REALLOC(mem, newsize);
}
size = newsize;
#ifdef _DEBUG
memblocks_totalsize += size;
#endif
return getMemory();
}
void *VoidMemBlock::setMinimumSize(int newminsize, int increment) {
if (newminsize > size) setSize(newminsize+increment);
return getMemory();
}
void VoidMemBlock::setMemory(const void *data, int datalen, int offsetby) {
if (datalen <= 0) return;
ASSERT(mem != NULL);
ASSERT(offsetby >= 0);
char *ptr = reinterpret_cast<char *>(mem);
ASSERT(ptr + offsetby + datalen <= ptr + size);
MEMCPY(ptr + offsetby, data, datalen);
}
int VoidMemBlock::getSize() const {
return size;
}
int VoidMemBlock::isMine(void *ptr) {
return (ptr >= mem && ptr < (char*)mem + size);
}
void VoidMemBlock::zeroMemory() {
if (mem == NULL || size < 1) return;
MEMZERO(mem, size);
}

101
Src/Wasabi/bfc/memblock.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef _MEMBLOCK_H
#define _MEMBLOCK_H
//#include <bfc/wasabi_std.h>
#include <bfc/std_mem.h>
//#include <wasabicfg.h>
#ifdef _DEBUG
extern int memblocks_totalsize;
#endif
class VoidMemBlock {
protected:
VoidMemBlock(int size=0, const void *data=0);
~VoidMemBlock();
void *setSize(int newsize);
void *setMinimumSize(int newminsize, int increment=0);
void *getMemory() const { return mem; }
void setMemory(const void *data, int datalen, int offsetby=0);
int getSize() const;
int isMine(void *ptr);
void zeroMemory();
private:
void *mem;
int size;
};
// just a convenient resizeable block of memory wrapper
// doesn't handle constructors or anything, meant for int, char, etc.
template <class T>
class MemBlock : private VoidMemBlock {
public:
MemBlock(int _size = 0, const T *data = NULL) : VoidMemBlock(_size*sizeof(T), data) {}
MemBlock(const MemBlock<T> &source) : VoidMemBlock(source.getSizeInBytes(), source.getMemory()) {}
MemBlock(const MemBlock<T> *source) : VoidMemBlock(source->getSizeInBytes(), source->getMemory()) {}
T *setSize(int newsize) {
return static_cast<T*>(VoidMemBlock::setSize(newsize * sizeof(T)));
}
T *setMinimumSize(int newminsize, int increment = 0) {
return static_cast<T*>(VoidMemBlock::setMinimumSize(newminsize * sizeof(T), increment*sizeof(T)));
}
T *getMemory() const { return static_cast<T *>(VoidMemBlock::getMemory()); }
T *getMemory(int offset) const { return static_cast<T *>(VoidMemBlock::getMemory())+offset; } // note pointer arithmetic
T *m() const { return getMemory(); }
T *m(int offset) const { return getMemory(offset); }
operator T *() const { return getMemory(); }
T& operator() (unsigned int ofs) { return getMemory()[ofs]; }
const T& operator() (unsigned int ofs) const { return getMemory()[ofs]; }
void copyTo(T *dest) { MEMCPY(getMemory(), dest, getSizeInBytes()); }
int getSize() const { return VoidMemBlock::getSize()/sizeof(T); }// # of T's
int getSizeInBytes() const { return VoidMemBlock::getSize(); }
int isMine(T *ptr) { return VoidMemBlock::isMine(ptr); }
void setMemory(const T *data, int datalen, int offsetby = 0) { VoidMemBlock::setMemory(data, datalen*sizeof(T), offsetby*sizeof(T)); } // # of T's
void zeroMemory() { VoidMemBlock::zeroMemory(); }
void reverse() {
const int nitems = getSize();
if (nitems <= 1) return;
MemBlock<T> nm(this);
T *mymem = getMemory(), *revmem = nm.getMemory();
for (int i = 0, j = nitems-1; j >= 0; i++, j--) {
MEMCPY(mymem+i, revmem+j, sizeof(T));
}
}
};
// just a convenience class for a 2d MemBlock<>
template <class T>
class MemMatrix : public MemBlock<T> {
public:
MemMatrix(int _width, int height, const T *data = NULL) : MemBlock<T>(_width * height, data), width(_width) {}
T *setSize(int _width, int height) {
MemBlock<T>::setSize(width * height);
width = _width;
}
// () access i.e. obj(x,y)
T& operator() (unsigned int x, unsigned int y) {
return *MemBlock<T>::m(x + y * width);
}
const T& operator() (unsigned int x, unsigned int y) const {
return *MemBlock<T>::m(x + y * width);
}
private:
int width;
};
#endif

412
Src/Wasabi/bfc/multipatch.h Normal file
View File

@ -0,0 +1,412 @@
#ifndef _WASABI_MULTIPATCH_H
#define _WASABI_MULTIPATCH_H
// (c) 2005 Nullsoft, Inc.
#include "dispatch.h"
/*
Author: Ben Allison <benski@nullsoft.com>
The purpose of the MultiPatch class is to allow a class to have multiple Dispatchable interfaces.
It is an alternative to the method of using a stub class with virtual functions.
(you see these classes all over Wasabi, either ending in I or X, depending on age)
Since each vtable entry costs 4 bytes per object (8 on 64bit), using this method adds some code size
(and, in some multiple-inheritance situations, memory per object for vtable overrides)
Of course, MultiPatch's dispatching function adds code size, too. But the function shouldn't be any
larger or slower than the dispatching in the api_X class anyway.
Using MultiPatch, each method call goes through this chain:
dispatch->multipatch->your class method
as opposed to:
dispatch->your class method (single inheritance)
or:
dispatch->virtual function->your class method (api_X method)
A clever compiler might be able to optimize away the _multipatch function call by
pushing "patch" on the top of the parameter stack and jmp'ing.
For an example on usage, scroll down to the bottom of the page.
*/
template <int patch_t, class base_t>
class MultiPatch : public base_t
{
protected:
virtual int _multipatch(int patch, int msg, void *retval, void **params=0, int nparam=0) = 0;
private:
int _dispatch(int msg, void *retval, void **params=0, int nparam=0)
{
return _multipatch(patch_t, msg, retval, params, nparam);
}
public:
/* these helper functions are a direct copy from Dispatchable...
* They need to be duplicated, because the compiler gets confused when trying to cast
* from Dispatchable to the child class (since that class has multiple Dispatchable parents)
*
* They could potentially be eliminated by modifying Dispatchable's versions, but the risk of breakage
* isn't worth it.
*/
template <class CLASSNAME, class RETVAL>
void cb(RETVAL (CLASSNAME::*fn)(), void *retval, void **params) {
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)();
}
template <class CLASSNAME>
void vcb(void (CLASSNAME::*fn)(), void *retval, void **params) {
(static_cast<CLASSNAME *>(this)->*fn)();
}
template <class CLASSNAME, class RETVAL, class PARAM1>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1);
}
template <class CLASSNAME, class PARAM1>
void vcb(void (CLASSNAME::*fn)(PARAM1), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1);
}
template <class CLASSNAME, class PARAM1, class PARAM2>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2);
}
// 3 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3);
}
// 4 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4);
}
// 5 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5);
}
// 6 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6);
}
// 7 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7);
}
// 8 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8);
}
// 9 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9);
}
// 10 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10);
}
template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
*static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10);
}
// 14 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14);
}
// 16 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
PARAM15 *p15 = static_cast<PARAM15*>(params[14]);
PARAM16 *p16 = static_cast<PARAM16*>(params[15]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16);
}
// 17 params
template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16, class PARAM17>
void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16, PARAM17), void *retval, void **params) {
PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
PARAM15 *p15 = static_cast<PARAM15*>(params[14]);
PARAM16 *p16 = static_cast<PARAM16*>(params[15]);
PARAM17 *p17 = static_cast<PARAM17*>(params[16]);
(static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16, *p17);
}
};
#define RECVS_MULTIPATCH int _multipatch(int patch, int msg, void *retval, void **params=0, int nparam=0)
#define START_MULTIPATCH \
int CBCLASS::_multipatch(int patch, int msg, void *retval, void **params, int nparam) { \
switch (patch) {
//FINISH case DESTRUCT: delete this; return 1;
#define END_MULTIPATCH \
default: return 0; \
} \
return 1; \
}
#define FORWARD_MULTIPATCH(x) \
default: return x::_multipatch(patch, msg, retval, params, nparam); \
} \
return 1; \
}
#define START_PATCH(x) case x: switch(msg) {
#define END_PATCH default: return 0; } break;
#define NEXT_PATCH(x) END_PATCH START_PATCH(x)
#define M_CB(p, c, x, y) case (x): MultiPatch<p,c>::cb(&CBCLASS::y, retval, params); break;
#define M_VCB(p, c, x, y) case (x): MultiPatch<p,c>::vcb(&CBCLASS::y, retval, params); break;
#define MULTIPATCH_CODES enum
#endif
/* use example:
enum
{
Test_Patch1 = 10,
Test_Patch2 = 20,
};
class Test : public MultiPatch<Test_Patch1, api_class1>,
public MultiPatch<Test_Patch2, api_class2>
{
public:
int TestFunc1();
void TestFunc2();
void TestFunc3();
protected:
RECVS_MULTIPATCH;
};
#ifdef CBCLASS
#undef CBCLASS
#endif
#define CBCLASS Test
START_MULTIPATCH;
START_PATCH(Test_Patch1)
M_CB(Test_Patch1, api_class1, API_CLASS1_FUNC1, TestFunc1);
NEXT_PATCH(Test_Patch2)
M_VCB(Test_Patch2, api_class2, API_CLASS1_FUNC1, TestFunc2);
M_VCB(Test_Patch2, api_class2, API_CLASS1_FUNC2, TestFunc3);
END_PATCH
END_MULTIPATCH;
#undef CBCLASS
*/

25
Src/Wasabi/bfc/named.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef _NAMED_H
#define _NAMED_H
#include <bfc/common.h>
#include <bfc/string/StringW.h>
class NOVTABLE NamedW
{
public:
NamedW(const wchar_t *initial_name=NULL) : name(initial_name) {}
virtual ~NamedW() {} // placeholder to ensure name is destructed properly
const wchar_t *getName() const { return name; }
const wchar_t *getNameSafe(const wchar_t *defval=NULL) const {
const wchar_t *str = name;
return str ? str : (defval ? defval : L"(null)");
}
void setName(const wchar_t *newname) { if (name.isequal(newname)) return; name = newname; onSetName(); }
// override this to catch name settings
virtual void onSetName() {}
private:
StringW name;
};
#endif

8
Src/Wasabi/bfc/node.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "precomp_wasabi_bfc.h"
#include "node.h"
// In debug mode, the node baseclass will keep track of the count
// of all nodes created, to help detect leakage of nodes.
#ifdef _DEBUG
int Node::count = 0;
#endif//_DEBUG

118
Src/Wasabi/bfc/node.h Normal file
View File

@ -0,0 +1,118 @@
#ifndef _NODE_H
#define _NODE_H
#include "ptrlist.h"
//
// node.h
//
// Some node classes.
//
// ==========================================================================
//
// class Node
//
// A generic "node" object from which one may subclass and create a set of
// disparate objects that may be assembled into a hierarchical tree.
//
class Node {
private:
PtrList<Node> childlist;
Node * parent;
protected:
#ifdef _DEBUG
static int count;
#endif//_DEBUG
public:
Node(Node * myParent = NULL) : childlist(), parent(myParent) {
#ifdef _DEBUG
count++;
#endif//_DEBUG
}
Node(const Node & a) : childlist(a.childlist), parent(a.parent) {
#ifdef _DEBUG
count++;
#endif//_DEBUG
}
virtual ~Node() {
#ifdef _DEBUG
count--;
#endif//_DEBUG
};
int nodeCount() {
#ifdef _DEBUG
return count;
#else //_DEBUG
return -1;
#endif//_DEBUG
}
//
// Const Data Accessor Methods
int getNumChildren() const {
return childlist.getNumItems();
}
Node * enumChild(int index) const {
return childlist[index];
}
Node * getParent() const {
return parent;
}
//
// Nonconst Data Manipulator Methods
Node * addChild(Node * child) {
child->setParent(this);
return childlist.addItem(child);
}
Node * setParent(Node * myParent) {
return parent = myParent;
}
PtrList< Node > & ChildList() {
return childlist;
}
};
// ==========================================================================
//
// class NodeC< TPayload >
//
// If you would rather use Node as a container class than as a base class,
// this object will allow you to contain a payload instance and be accessed
// as if it were the payload instance using a reference operator and an
// implicit cast operator.
//
template < class TPayload >
class NodeC : public Node {
protected:
TPayload payload;
public:
NodeC( const TPayload & myPayload, NodeC * myParent = NULL ) : Node( myParent ), payload( myPayload ) {}
NodeC( const NodeC & a ) : Node( a ), payload( a.payload ) {}
//
// In addition to being able to call all of the Node methods, you can also
// simply treat the node objects themselves as if they were the payload
// instantiation through these simple methods:
// Explicit reference operator - for lvalues and force rvalues.
TPayload & operator () ( void ) { return payload; }
// Implicit cast operator - for rvalues that can accept a TPayload &
operator TPayload & ( void ) { return payload; }
};
#endif//_NODE_H

174
Src/Wasabi/bfc/nsguid.cpp Normal file
View File

@ -0,0 +1,174 @@
#include "nsguid.h"
#include <bfc/wasabi_std.h>
#ifdef LINUX
#include <uuid/uuid.h>
#endif
char *nsGUID::toChar(const GUID &guid, char *target)
{
// {1B3CA60C-DA98-4826-B4A9-D79748A5FD73}
SPRINTF( target, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
(int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
(int)guid.Data4[0], (int)guid.Data4[1],
(int)guid.Data4[2], (int)guid.Data4[3],
(int)guid.Data4[4], (int)guid.Data4[5],
(int)guid.Data4[6], (int)guid.Data4[7] );
return target;
}
char *nsGUID::toCode(const GUID &guid, char *target)
{
//{ 0x1b3ca60c, 0xda98, 0x4826, { 0xb4, 0xa9, 0xd7, 0x97, 0x48, 0xa5, 0xfd, 0x73 } };
SPRINTF( target, "{ 0x%08x, 0x%04x, 0x%04x, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } };",
(int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
(int)guid.Data4[0], (int)guid.Data4[1],
(int)guid.Data4[2], (int)guid.Data4[3],
(int)guid.Data4[4], (int)guid.Data4[5],
(int)guid.Data4[6], (int)guid.Data4[7] );
return target;
}
GUID nsGUID::fromCode(const char *source) {
GUID guid = GUID_NULL;
int Data1, Data2, Data3;
int Data4[8] = {0};
//{ 0x1b3ca60c, 0xda98, 0x4826, { 0xb4, 0xa9, 0xd7, 0x97, 0x48, 0xa5, 0xfd, 0x73 } };
SSCANF( source, " { 0x%08x, 0x%04x, 0x%04x, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } } ; ",
&Data1, &Data2, &Data3, Data4 + 0, Data4 + 1,
Data4 + 2, Data4 + 3, Data4 + 4, Data4 + 5, Data4 + 6, Data4 + 7 );
// Cross assign all the values
guid.Data1 = Data1;
guid.Data2 = Data2;
guid.Data3 = Data3;
guid.Data4[0] = Data4[0];
guid.Data4[1] = Data4[1];
guid.Data4[2] = Data4[2];
guid.Data4[3] = Data4[3];
guid.Data4[4] = Data4[4];
guid.Data4[5] = Data4[5];
guid.Data4[6] = Data4[6];
guid.Data4[7] = Data4[7];
return guid;
}
int nsGUID::compare(const GUID &a, const GUID &b) {
int delta1 = a.Data1 - b.Data1;
if (delta1 == 0) {
int delta2 = a.Data2 - b.Data2;
if (delta2 == 0) {
int delta3 = a.Data3 - b.Data3;
if (delta3 == 0) {
int i;
for (i = 0; i < 8; i++ ) {
int delta4 = a.Data4[i] - b.Data4[i];
if (delta4 == 0) {
continue; // :)
} else {
return delta4;
}
}
} else {
return delta3;
}
} else {
return delta2;
}
} else {
return delta1;
}
return 0;
}
#ifdef WASABI_COMPILE_CREATEGUID
void nsGUID::createGuid(GUID *g) {
#ifdef WIN32
CoCreateGuid(g);
#else
uuid_t uid;
uuid_generate(uid);
MEMCPY(g, &uid, MIN((int)sizeof(GUID), (int)sizeof(uuid_t)));
#endif
}
#endif
wchar_t *nsGUID::toCharW(const GUID &guid, wchar_t *target)
{
// {1B3CA60C-DA98-4826-B4A9-D79748A5FD73}
WCSNPRINTF(target, 39, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
(int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
(int)guid.Data4[0], (int)guid.Data4[1],
(int)guid.Data4[2], (int)guid.Data4[3],
(int)guid.Data4[4], (int)guid.Data4[5],
(int)guid.Data4[6], (int)guid.Data4[7] );
return target;
}
GUID nsGUID::fromCharW(const wchar_t *source)
{
if (source == NULL) return INVALID_GUID;
if (!WCSICMP(source, L"@all@"))
{
static GUID g={ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
return g;
}
if (WCSNICMP(source, L"guid:{", 6)==0)
{
source+=5;
}
if(WCSICMP(source, L"guid:avs")==0) {
static GUID g={ 10, 12, 16, { 255, 123, 1, 1, 66, 99, 69, 12 } };
return g;
}
if (WCSICMP(source, L"guid:pl")==0 || WCSICMP(source, L"guid:playlist")==0) {
static GUID g={ 0x45f3f7c1, 0xa6f3, 0x4ee6, { 0xa1, 0x5e, 0x12, 0x5e, 0x92, 0xfc, 0x3f, 0x8d } };
return g;
}
if (WCSICMP(source, L"guid:ml")==0 || WCSICMP(source, L"guid:musiclibrary")==0 || WCSICMP(source, L"guid:library")==0) {
static GUID g={ 0x6b0edf80, 0xc9a5, 0x11d3, { 0x9f, 0x26, 0x00, 0xc0, 0x4f, 0x39, 0xff, 0xc6 } };
return g;
}
if (WCSICMP(source, L"guid:default")==0) {
static GUID g={ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
return g;
}
if (!wcschr(source, '{') || !wcschr(source, '}'))
return INVALID_GUID;
GUID guid = GUID_NULL;
int Data1, Data2, Data3;
int Data4[8] = {0};
// {1B3CA60C-DA98-4826-B4A9-D79748A5FD73}
int n = swscanf( source, L" { %08x - %04x - %04x - %02x%02x - %02x%02x%02x%02x%02x%02x } ",
&Data1, &Data2, &Data3, Data4 + 0, Data4 + 1,
Data4 + 2, Data4 + 3, Data4 + 4, Data4 + 5, Data4 + 6, Data4 + 7 );
if (n != 11) return INVALID_GUID;
// Cross assign all the values
guid.Data1 = Data1;
guid.Data2 = Data2;
guid.Data3 = Data3;
guid.Data4[0] = Data4[0];
guid.Data4[1] = Data4[1];
guid.Data4[2] = Data4[2];
guid.Data4[3] = Data4[3];
guid.Data4[4] = Data4[4];
guid.Data4[5] = Data4[5];
guid.Data4[6] = Data4[6];
guid.Data4[7] = Data4[7];
return guid;
}

33
Src/Wasabi/bfc/nsguid.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef _NSGUID_H
#define _NSGUID_H
#include "../../replicant/foundation/guid.h"
#include <bfc/platform/guid.h>
//#include <bfc/common.h>
// Some conversion functions to allow
// us to have GUIDs translatable to and from other data types.
class nsGUID {
public:
// To the "Human Readable" character format.
// {1B3CA60C-DA98-4826-B4A9-D79748A5FD73}
static char *toChar(const GUID &guid, char *target);
static wchar_t *toCharW(const GUID &guid, wchar_t *target);
static GUID fromCharW(const wchar_t *source);
// To the "C Structure" character format.
// { 0x1b3ca60c, 0xda98, 0x4826, { 0xb4, 0xa9, 0xd7, 0x97, 0x48, 0xa5, 0xfd, 0x73 } };
static char *toCode(const GUID &guid, char *target);
static GUID fromCode(const char *source);
// Compare function, returns -1, 0, 1
static int compare(const GUID &a, const GUID &b);
// strlen("{xx xxx xxx-xxxx-xxxx-xxxx-xxx xxx xxx xxx}"
enum { GUID_STRLEN = 38 };
#ifdef WASABI_COMPILE_CREATEGUID
static void createGuid(GUID *g);
#endif
};
#endif //_NSGUID_H

14
Src/Wasabi/bfc/pair.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _PAIR_H
#define _PAIR_H
template <class A, class B>
class Pair {
public:
Pair() {}
Pair(A _a, B _b) : a(_a), b(_b) {}
A a;
B b;
};
#endif

View File

@ -0,0 +1,4 @@
INCLUDES = -I$(top_srcdir)/src $(all_includes)
METASOURCES = AUTO
noinst_HEADERS = hierarchyparser.h paramparser.h pathparse.h

View File

@ -0,0 +1,372 @@
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AR = @AR@
AS = @AS@
CC = @CC@
CXX = @CXX@
CXXCPP = @CXXCPP@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
HAVE_LIB = @HAVE_LIB@
LIB = @LIB@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
MAKEINFO = @MAKEINFO@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@
VERSION = @VERSION@
INCLUDES = -I$(top_srcdir)/src $(all_includes)
METASOURCES = AUTO
noinst_LTLIBRARIES = libbfc_parse.la
libbfc_parse_la_SOURCES = hierarchyparser.cpp paramparser.cpp pathparse.cpp
noinst_HEADERS = hierarchyparser.h paramparser.h pathparse.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../../config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I../../..
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libbfc_parse_la_LDFLAGS =
libbfc_parse_la_LIBADD =
libbfc_parse_la_OBJECTS = hierarchyparser.lo paramparser.lo \
pathparse.lo
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
HEADERS = $(noinst_HEADERS)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/hierarchyparser.P .deps/paramparser.P \
.deps/pathparse.P
SOURCES = $(libbfc_parse_la_SOURCES)
OBJECTS = $(libbfc_parse_la_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .cpp .lo .o .obj .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bfc/parse/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLTLIBRARIES:
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
distclean-noinstLTLIBRARIES:
maintainer-clean-noinstLTLIBRARIES:
# FIXME: We should only use cygpath when building on Windows,
# and only if it is available.
.c.obj:
$(COMPILE) -c `cygpath -w $<`
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
-rm -f *.$(OBJEXT)
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
libbfc_parse.la: $(libbfc_parse_la_OBJECTS) $(libbfc_parse_la_DEPENDENCIES)
$(CXXLINK) $(libbfc_parse_la_LDFLAGS) $(libbfc_parse_la_OBJECTS) $(libbfc_parse_la_LIBADD) $(LIBS)
.cpp.o:
$(CXXCOMPILE) -c $<
.cpp.obj:
$(CXXCOMPILE) -c `cygpath -w $<`
.cpp.lo:
$(LTCXXCOMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src/bfc/parse
distdir: $(DISTFILES)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(top_distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/bfc/parse/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-include $(DEP_FILES)
mostlyclean-depend:
clean-depend:
distclean-depend:
-rm -rf .deps
maintainer-clean-depend:
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
%.lo: %.c
@echo '$(LTCOMPILE) -c $<'; \
$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*F).pp > .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm -f .deps/$(*F).pp
%.o: %.cpp
@echo '$(CXXCOMPILE) -c $<'; \
$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
%.lo: %.cpp
@echo '$(LTCXXCOMPILE) -c $<'; \
$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*F).pp > .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm -f .deps/$(*F).pp
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLTLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLTLIBRARIES clean-compile clean-libtool \
clean-tags clean-depend clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLTLIBRARIES distclean-compile \
distclean-libtool distclean-tags distclean-depend \
distclean-generic clean-am
-rm -f libtool
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLTLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-tags maintainer-clean-depend \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \
clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir \
mostlyclean-depend distclean-depend clean-depend \
maintainer-clean-depend info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,55 @@
#include <bfc/bfc_assert.h>
#include "pathparse.h"
PathParserW::PathParserW(const wchar_t *_str, const wchar_t *sep, int uniquestrs) :
processed(FALSE), str(_str ? _str : L""), separators(sep), uniques(uniquestrs)
{
ASSERT(sep != NULL);
}
int PathParserW::getNumStrings() {
process();
return strings.getNumItems();
}
wchar_t *PathParserW::enumString(int i) {
process();
return strings[i];
}
wchar_t *PathParserW::enumStringSafe(int i, wchar_t *def_val) {
wchar_t *ret = enumString(i);
if (ret == NULL) ret = def_val;
return ret;
}
void PathParserW::process() {
if (processed) return;
processed = 1;
preProcess(str);
wchar_t *nonconst = str.getNonConstVal();
wchar_t *context=0;
wchar_t *pt = WCSTOK(nonconst, separators, &context);
if (pt == NULL) return;
postProcess(pt);
strings.addItem(pt);
for (;;) {
wchar_t *pt = WCSTOK(NULL, separators, &context);
if (pt == NULL) break;
postProcess(pt);
if (uniques) {
int exists = 0;
foreach(strings)
if (!WCSICMP(strings.getfor(), pt))
{
exists=1;
break;
}
endfor;
if (exists) continue;
}
strings.addItem(pt);
}
}

View File

@ -0,0 +1,99 @@
#include "precomp_wasabi_bfc.h"
#include "hierarchyparser.h"
#include <bfc/nsguid.h>
#include <wchar.h>
// This uses an AMAZINGLY inefficient algorithm! woo hoo!
HierarchyParser::HierarchyParser(const wchar_t *str, const wchar_t *_sibling, const wchar_t *_escape, const wchar_t *_parent_open, const wchar_t *_parent_close) {
// Create a new rootnode.
rootnode = new HPNode(str);
// Parse the rootnode's contents into the rootnode's children.
HierarchyParser downparse(rootnode, _sibling, _escape, _parent_open, _parent_close);
// Set the actual name of the rootnode ("")
(*rootnode)() = L"";
// Mark that this was our allocation
myalloc = 1;
}
HierarchyParser::~HierarchyParser() {
// If we alloc, we must delete.
if (myalloc) {
delete rootnode;
}
}
HPNode *HierarchyParser::findGuid(GUID g) {
return NULL;
}
HPNode *HierarchyParser::findString(const wchar_t *str) {
return NULL;
}
HierarchyParser::HierarchyParser(HPNode *_rootnode, const wchar_t *_sibling, const wchar_t *_escape, const wchar_t *_parent_open, const wchar_t *_parent_close) {
// We did not alloc, we should not delete.
rootnode = _rootnode;
sibling = _sibling;
escape = _escape;
parent_open = _parent_open;
parent_close = _parent_close;
myalloc = 0;
const wchar_t *parsestr = (*rootnode)();
size_t i, length = wcslen(parsestr), depth = 0;
StringW curr_sibling;
for (i = 0; i < length; i++ ) {
wchar_t c = parsestr[i];
if (isEscape(c)) {
// always add the next character
curr_sibling += parsestr[++i];
} else if (isSibling(c)) {
// if we're not inside someone else,
if (!depth) {
// okay, we're done with the current sibling. ship him off.
processSibling(curr_sibling);
// on to the next sibling!
curr_sibling = L"";
} else {
curr_sibling += c;
}
} else if (isParentOpen(c)) {
// increment depth
curr_sibling += c;
depth++;
} else if (isParentClose(c)) {
// decrement depth
curr_sibling += c;
depth--;
} else {
curr_sibling += c;
}
}
// If there is anything left over, process it as a sibling.
if (curr_sibling.len()) {
processSibling(curr_sibling);
}
}
void HierarchyParser::processSibling(const wchar_t *sibstr) {
StringW curr_sibling = sibstr;
// slice the name out of the front of the string.
StringW sibling_name = curr_sibling.lSpliceChar(parent_open);
// curr_sibling will contain the children of this sibling (or nothing).
curr_sibling.rSpliceChar(parent_close);
// create a new child for our root node to contain the sibling's child info
HPNode *child = new HPNode(curr_sibling, rootnode);
// parse the child hierarchically for its children
HierarchyParser childparser(child, sibling, escape, parent_open, parent_close);
// once parsed. set its name to be this sibling
(*child)() = sibling_name;
// and lastly add him as a child to the root node.
rootnode->addChild(child);
}

View File

@ -0,0 +1,55 @@
#ifndef __PARAMPARSE_H
#define __PARAMPARSE_H
#include <bfc/parse/pathparse.h>
#include <bfc/node.h>
#include <bfc/string/StringW.h>
// typedef NodeC<String> HPNode // OH YAH, YOU CAN'T FWD REF TYPEDEFS. STOOOOOOPID.
class HPNode : public NodeC<StringW> {
public:
HPNode( const StringW & myPayload, NodeC<StringW> * myParent = NULL ) : NodeC<StringW>(myPayload, myParent) {}
};
class HierarchyParser {
public:
HierarchyParser(const wchar_t *str = NULL, const wchar_t *_sibling=L";", const wchar_t *_escape=L"\\", const wchar_t *_parent_open=L"(", const wchar_t *_parent_close=L")") ;
~HierarchyParser();
HPNode *findGuid(GUID g);
HPNode *findString(const wchar_t *str);
int hasGuid(GUID g) { return findGuid(g) != NULL; }
int hasString(const wchar_t *str) { return findString(str) != NULL; }
HPNode *rootNode() { return rootnode; }
private:
HPNode *rootnode;
int myalloc;
StringW sibling;
StringW escape;
StringW parent_open;
StringW parent_close;
HierarchyParser(HPNode *_rootnode, const wchar_t *_sibling=L";", const wchar_t *_escape=L"\\", const wchar_t *_parent_open=L"(", const wchar_t *_parent_close=L")");
void processSibling(const wchar_t *sibling);
inline int isSibling(wchar_t c) {
return sibling.lFindChar(c) != -1;
}
inline int isEscape(wchar_t c) {
return escape.lFindChar(c) != -1;
}
inline int isParentOpen(wchar_t c) {
return parent_open.lFindChar(c) != -1;
}
inline int isParentClose(wchar_t c) {
return parent_close.lFindChar(c) != -1;
}
};
#endif

View File

@ -0,0 +1,20 @@
#include "precomp_wasabi_bfc.h"
#include "paramparser.h"
#include <bfc/nsguid.h>
#include <bfc/wasabi_std.h>
int ParamParser::findGuid(GUID g) {
for (int i=0;i<getNumItems();i++) {
const wchar_t *e = enumItem(i);
GUID eguid = nsGUID::fromCharW(e);
if (g == eguid) return i;
}
return -1;
}
int ParamParser::findString(const wchar_t *str) {
for (int i=0;i<getNumItems();i++) {
if (!WCSICMP(str, enumItem(i))) return i;
}
return -1;
}

View File

@ -0,0 +1,23 @@
#ifndef __PARAMPARSE_H
#define __PARAMPARSE_H
#include <bfc/parse/pathparse.h>
class ParamParser : private PathParserW
{
public:
ParamParser(const wchar_t *str, const wchar_t *sep=L";", int unique=0) : PathParserW(str, sep, unique) {}
int findGuid(GUID g);
int findString(const wchar_t *str);
int hasGuid(GUID g) { return findGuid(g) >= 0; }
int hasString(const wchar_t *str) { return findString(str) >= 0; }
const wchar_t *enumItem(int element) { return enumString(element); }
int getNumItems() { return getNumStrings(); }
const wchar_t *getLastItem() { return getLastString(); }
};
#endif

View File

@ -0,0 +1,54 @@
#include "precomp_wasabi_bfc.h"
#include <bfc/wasabi_std.h>
#include "pathparse.h"
PathParser::PathParser(const char *_str, const char *sep, int uniquestrs) :
processed(FALSE), str(_str ? _str : ""), separators(sep), uniques(uniquestrs)
{
ASSERT(sep != NULL);
}
int PathParser::getNumStrings() {
process();
return strings.getNumItems();
}
char *PathParser::enumString(int i) {
process();
return strings[i];
}
char *PathParser::enumStringSafe(int i, char *def_val) {
char *ret = enumString(i);
if (ret == NULL) ret = def_val;
return ret;
}
void PathParser::process() {
if (processed) return;
processed = 1;
preProcess(str);
char *nonconst = str.getNonConstVal();
char *pt = strtok(nonconst, separators);
if (pt == NULL) return;
postProcess(pt);
strings.addItem(pt);
for (;;) {
char *pt = strtok(NULL, separators);
if (pt == NULL) break;
postProcess(pt);
if (uniques) {
int exists = 0;
foreach(strings)
if (STRCASEEQL(strings.getfor(), pt)) {
exists=1;
break;
}
endfor;
if (exists) continue;
}
strings.addItem(pt);
}
}

View File

@ -0,0 +1,152 @@
#ifndef _PATHPARSE_H
#define _PATHPARSE_H
#include <bfc/ptrlist.h>
#include <bfc/string/bfcstring.h>
#include <bfc/string/StringW.h>
/**
PathParser is a class that parses a DOS/Windows (example: C:\DOS)
style path as well as a UNIX style path (example: /usr/local/bin/).
@short Path parser for Windows and UNIX style paths.
@author Nullsoft
@ver 1.0
*/
class PathParser
{
public:
/**
When PathParser is instantiated, the contructor takes the path to
parse and the separators to use to parse the path. It will then
parse the path using the separators and make the parsed elements
available. If no separators are given \ and / are used.
@param str The path to parse.
@param separators String that contains the separators to use. Single character separators only.
No delimiters between separators in the string.
*/
PathParser(const char *_str, const char *sep = "\\/", int uniquestrs = 0);
void setString(const char *string, const char *separators = "\\/");
/**
Gets the number of path elements found in the path.
@ret The number of path elements found.
*/
int getNumStrings();
/**
Gets the number of path elements found in the path.
@ret The number of path elements found.
*/
char *enumString(int i);
char *enumStringSafe(int i, char *def_val="");
/**
Gets the last path element from the parsed path.
@ret The last path element from the parsed path.
*/
char *getLastString() { return enumString(getNumStrings()-1); }
protected:
/**
Override available for pre-processing of the
string before it's split. This is done at the start
of the process() call.
@param str A reference to the string to pre-process.
*/
virtual void preProcess(String &str) { }
/**
Override available for post-processing of the pieces
of the command line that are obtained after it's
been split.
@param str The command line piece to post-process.
*/
virtual void postProcess(char *str) { }
private:
void process();
int processed;
String str;
String separators;
PtrList<char> strings;
int uniques;
};
class PathParserW
{
public:
/**
When PathParser is instantiated, the contructor takes the path to
parse and the separators to use to parse the path. It will then
parse the path using the separators and make the parsed elements
available. If no separators are given \ and / are used.
@param str The path to parse.
@param separators String that contains the separators to use. Single character separators only.
No delimiters between separators in the string.
*/
PathParserW(const wchar_t *_str, const wchar_t *sep = L"\\/", int uniquestrs = 0);
void setString(const wchar_t *string, const wchar_t *separators = L"\\/");
/**
Gets the number of path elements found in the path.
@ret The number of path elements found.
*/
int getNumStrings();
/**
Gets the number of path elements found in the path.
@ret The number of path elements found.
*/
wchar_t *enumString(int i);
wchar_t *enumStringSafe(int i, wchar_t *def_val=L"");
/**
Gets the last path element from the parsed path.
@ret The last path element from the parsed path.
*/
wchar_t *getLastString() { return enumString(getNumStrings()-1); }
protected:
/**
Override available for pre-processing of the
string before it's split. This is done at the start
of the process() call.
@param str A reference to the string to pre-process.
*/
virtual void preProcess(StringW &str) { }
/**
Override available for post-processing of the pieces
of the command line that are obtained after it's
been split.
@param str The command line piece to post-process.
*/
virtual void postProcess(wchar_t *str) { }
private:
void process();
int processed;
StringW str;
StringW separators;
PtrList<wchar_t> strings;
int uniques;
};
#endif

View File

@ -0,0 +1,6 @@
INCLUDES = -I$(top_srcdir)/src $(all_includes)
METASOURCES = AUTO
noinst_LIBRARIES = libbfc_platform.a
libbfc_platform_a_SOURCES = guid.h linux.h platform.h platform.cpp
libbfc_platform_a_LIBADD = $(top_builddir)/src/bfc/platform/linux/libbfc_platform_linux.a

View File

@ -0,0 +1,376 @@
# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AR = @AR@
AS = @AS@
CC = @CC@
CXX = @CXX@
CXXCPP = @CXXCPP@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
HAVE_LIB = @HAVE_LIB@
LIB = @LIB@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIB = @LTLIB@
MAKEINFO = @MAKEINFO@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
RC = @RC@
STRIP = @STRIP@
VERSION = @VERSION@
INCLUDES = -I$(top_srcdir)/src $(all_includes)
METASOURCES = AUTO
noinst_LIBRARIES = libbfc_platform.a
libbfc_platform_a_SOURCES = guid.h linux.h platform.h platform.cpp
libbfc_platform_a_LIBADD = $(top_builddir)/src/bfc/platform/linux/libbfc_platform_linux.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../../config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I../../..
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libbfc_platform_a_DEPENDENCIES = \
$(top_builddir)/src/bfc/platform/linux/libbfc_platform_linux.a
libbfc_platform_a_OBJECTS = platform.$(OBJEXT)
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/platform.P
SOURCES = $(libbfc_platform_a_SOURCES)
OBJECTS = $(libbfc_platform_a_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .cpp .lo .o .obj .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bfc/platform/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
# FIXME: We should only use cygpath when building on Windows,
# and only if it is available.
.c.obj:
$(COMPILE) -c `cygpath -w $<`
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
-rm -f *.$(OBJEXT)
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
.s.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
.S.lo:
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
maintainer-clean-libtool:
libbfc_platform.a: $(libbfc_platform_a_OBJECTS) $(libbfc_platform_a_DEPENDENCIES)
-rm -f libbfc_platform.a
$(AR) cru libbfc_platform.a $(libbfc_platform_a_OBJECTS) $(libbfc_platform_a_LIBADD)
$(RANLIB) libbfc_platform.a
.cpp.o:
$(CXXCOMPILE) -c $<
.cpp.obj:
$(CXXCOMPILE) -c `cygpath -w $<`
.cpp.lo:
$(LTCXXCOMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src/bfc/platform
distdir: $(DISTFILES)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(top_distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/bfc/platform/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-include $(DEP_FILES)
mostlyclean-depend:
clean-depend:
distclean-depend:
-rm -rf .deps
maintainer-clean-depend:
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
%.lo: %.c
@echo '$(LTCOMPILE) -c $<'; \
$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*F).pp > .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm -f .deps/$(*F).pp
%.o: %.cpp
@echo '$(CXXCOMPILE) -c $<'; \
$(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
%.lo: %.cpp
@echo '$(LTCXXCOMPILE) -c $<'; \
$(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*F).pp > .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm -f .deps/$(*F).pp
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \
clean-depend clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-libtool distclean-tags distclean-depend \
distclean-generic clean-am
-rm -f libtool
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-tags maintainer-clean-depend \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir \
mostlyclean-depend distclean-depend clean-depend \
maintainer-clean-depend info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,20 @@
#ifndef NULLSOFT_BFC_EXPORT_H
#define NULLSOFT_BFC_EXPORT_H
#ifdef _MSC_VER
#define DLLEXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#error port me!
#endif
#ifdef _MSC_VER
#define DLLIMPORT __declspec(dllimport)
#elif defined(__GNUC__)
#define DLLIMPORT
#else
#error port me!
#endif
#endif

View File

@ -0,0 +1 @@
#include "../../../replicant/foundation/guid.h"

View File

@ -0,0 +1,437 @@
#ifndef __LINUX_H_WASABI
#define __LINUX_H_WASABI
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/timeb.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include <strings.h>
#include <sys/shm.h>
#ifndef NOVTABLE
#define NOVTABLE
#endif
#ifndef __USE_GNU
#define __USE_GNU
#include <pthread.h>
#undef __USE_GNU
#else
#include <pthread.h>
#endif
#ifdef WASABI_COMPILE_WND
// Fucking api_region and Font namespace conflicts
#define _XRegion _XRegion
#define api_region HRGN
#define Font HFONT
#define Cursor _Cursor
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/XShm.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/xpm.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#undef _XRegion
#undef api_region
#undef Font
#undef Cursor
#ifdef WASABI_COMPILE_FONTS
#ifdef __INCLUDE_FREETYPE
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#endif // freetype
//typedef FT_Face HFONT;
#endif // fonts
#ifdef __INCLUDE_GTK
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#endif // gtk
typedef Window HWND;
#else // wnd
typedef void * HWND;
#endif // wnd
// I know about XRectangle, but it's easier to recreate this than it is
// to merge it with the rest of the code
typedef struct { int left, top, right, bottom; } RECT;
typedef unsigned long COLORREF;
typedef struct {
char rgbBlue;
char rgbGreen;
char rgbRed;
char filler;
} RGBQUAD;
#define RGB( r, g, b ) ((((r)&0xFF)<<16)|(((g)&0xFF)<<8)|((b)&0xFF))
#define min( a, b ) ((a>b)?b:a)
#define max( a, b ) ((a>b)?a:b)
#define CLR_NONE 0
#ifdef __cplusplus
#ifndef XMD_H
typedef int BOOL; // It's int not bool because of some inheritance conflicts
#endif
#ifndef TRUE
#define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif
#else
#ifndef XMD_H
typedef int BOOL;
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#endif
typedef BOOL BOOLEAN;
typedef struct { int x, y; } POINT;
#ifdef WASABI_COMPILE_WND
typedef void *HPEN;
// The HDC knows what it's drawing on
typedef struct hdc_typ {
GC gc;
Drawable d;
HRGN clip;
} *HDC;
// Pixmaps don't have associated width and height, at least not that I know of
typedef struct {
Pixmap p;
int bmWidth;
int bmHeight;
XShmSegmentInfo *shmseginfo;
} BITMAP, HBITMAP;
typedef Pixmap HICON;
#endif // wnd
typedef int LRESULT;
typedef int LPARAM;
typedef int WPARAM;
typedef int RPARAM;
typedef unsigned int TCHAR;
typedef long long __int64;
typedef long long LARGE_INTEGER;
typedef unsigned long long ULARGE_INTEGER;
#define OSPIPE int
#define OSPROCESSID int
#define LOWORD(a) ((a)&0xffff)
#define HIWORD(a) (((a)>>16)&0xffff)
#define MAX_PATH 8192
#define COMEXP
#define EXTC extern "C"
#define __cdecl
#define CALLBACK
#define WINAPI
#define HRESULT void*
#define WINUSERAPI
#define APIENTRY
#define __declspec(a)
typedef char * LPSTR;
typedef unsigned long DWORD;
typedef short int WORD;
#ifndef XMD_H
typedef unsigned char BYTE;
#endif
typedef void* LPVOID;
typedef struct {
long cx, cy;
} SIZE;
typedef long LONG;
#define VOID void
#ifdef WASABI_COMPILE_WND
// Fix this for canvas
typedef void * PAINTSTRUCT;
#endif
#ifndef WASABI_COMPILE_WND
#ifndef None
#define None (HWND)0
#endif
#endif
typedef void* THREAD_RET;
#ifdef WASABI_COMPILE_WND
// Fix this with editwnd!
typedef void * WNDPROC;
typedef void * DRAWITEMSTRUCT;
#define VK_MENU (XK_Alt_L | (XK_Alt_R << 16))
#define VK_MBUTTON (XK_Meta_L | (XK_Meta_R << 16))
#define VK_SHIFT (XK_Shift_L | (XK_Shift_R << 16))
#define MK_RBUTTON ((XK_VoidSymbol << 16) | 1)
#define MK_LBUTTON ((XK_VoidSymbol << 16) | 2)
#define VK_CONTROL (XK_Control_L | (XK_Control_R << 16))
#define VK_DELETE (XK_Delete | (XK_KP_Delete << 16))
#define VK_RETURN (XK_Return)
#define VK_ESCAPE (XK_Escape)
#define VK_DOWN (XK_Down)
#define VK_UP (XK_Up)
#define VK_LEFT (XK_Left)
#define VK_RIGHT (XK_Right)
#define VK_HOME (XK_Home)
#define VK_END (XK_End)
#define VK_PRIOR (XK_Prior)
#define VK_NEXT (XK_Next)
#define VK_BACK (XK_BackSpace)
#define VK_F1 (XK_F1)
#define VK_SPACE (XK_space)
#define INVALID_HANDLE_VALUE NULL
#endif
// Come back here later
typedef struct {
pthread_mutex_t mutex;
pthread_t id;
int count;
} CRITICAL_SECTION;
typedef pthread_t HANDLE;
typedef char OLECHAR;
//#define NO_MMX
//CUT? #define NULLREGION 0
#define MAIN_MINX 0
#define MAIN_MINY 0
typedef void (*TIMERPROC)(HWND, UINT, UINT, DWORD);
typedef struct {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
#ifdef __cplusplus
#define _TRY try
#define _EXCEPT(x) catch(...)
#include <new>
#ifdef WASABI_COMPILE_WND
#define NULLREGION 1
#define SIMPLEREGION 2
#define COMPLEXREGION 3
#endif
// some of these are used even without wnd support
enum {
WM_CREATE, // MULL
WM_CLOSE, // NULL
WM_PAINT, // NULL
WM_NCPAINT, // NULL
WM_SYNCPAINT, // NULL
WM_SETCURSOR, // NULL
WM_TIMER, // timerid
WM_SETFOCUS, // NULL
WM_KILLFOCUS, // NULL
WM_LBUTTONDOWN, // xPos | yPos << 16
WM_RBUTTONDOWN, // "
WM_MOUSEMOVE, // "
WM_LBUTTONUP, // "
WM_RBUTTONUP, // "
WM_CONTEXTMENU, // "
WM_ERASEBKGND, // NULL
WM_MOUSEWHEEL, // a << 16 | t (l=a/120)
WM_CHAR, // char
WM_KEYDOWN, // keypress
WM_KEYUP, // "
WM_SYSKEYDOWN, // look at OnSysKeyDown
WM_SYSKEYUP, // "
WM_SYSCOMMAND, // Hunh?
WM_MOUSEACTIVATE, // Hunh?
WM_ACTIVATEAPP, // Hunh?
WM_ACTIVATE, // WA_ACTIVE || WA_CLICKACTIVE
WM_NCACTIVATE, // NULL
WM_WINDOWPOSCHANGED, // NULL, WINDOWPOS *
WM_DROPFILES, // HDROP
WM_CAPTURECHANGED, // NULL
WM_COMMAND, // Commands?..
WM_SETTINGCHANGE,
WM_QUIT,
WM_DESTROY,
WM_USER = 1000, // wParam, lParam -> make sure this is last
};
#define PM_NOREMOVE 0x0000
#define PM_REMOVE 0x0001
#define PM_NOYIELD 0x0002 // ignored
#ifdef WASABI_COMPILE_WND
enum {
WA_ACTIVE, WA_CLICKACTIVE,
};
enum {
SC_CLOSE,
};
enum {
DT_LEFT,
DT_CENTER,
DT_RIGHT,
DT_VCENTER,
DT_WORDBREAK,
DT_SINGLELINE,
DT_NOPREFIX,
DT_PATH_ELLIPSIS,
DT_END_ELLIPSIS,
DT_MODIFYSTRING,
DT_CALCRECT,
};
#define ALL_EVENTS ExposureMask | StructureNotifyMask | \
KeyPressMask | KeyReleaseMask | \
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | FocusChangeMask | \
EnterWindowMask | LeaveWindowMask
#define NO_INPUT_EVENTS ExposureMask | StructureNotifyMask | \
PointerMotionMask | FocusChangeMask | \
EnterWindowMask | LeaveWindowMask
class Linux {
private:
static Display *display;
static XContext context;
public:
static Display *getDisplay();
static int getScreenNum();
static Window RootWin();
static Visual *DefaultVis();
static int convertEvent( MSG *, XEvent * );
static void initContextData( HWND h );
static void nukeContextData( HWND h );
static XContext getContext();
static void setCursor( HWND h, int cursor );
};
#endif
#endif
typedef void* HINSTANCE; // Useless, just a placeholder
typedef void* HMONITOR;
typedef void* WIN32_FIND_DATA;
typedef void* WIN32_FIND_DATAW;
typedef void* BLENDFUNCTION;
typedef void* ATOM;
typedef void* HGLOBAL;
typedef void* HKEY;
typedef char* LPTSTR;
typedef char* LPCTSTR;
typedef DWORD* LPDWORD;
#if defined(WASABI_API_TIMER) || defined(WASABI_API_WND)
int GetMessage( MSG *, HWND, UINT, UINT );
int PeekMessage( MSG *, HWND, UINT, UINT, UINT );
int DispatchMessage( MSG * );
int SendMessage( HWND, UINT, WPARAM, LPARAM );
int SetTimer( HWND, int id, int ms, TIMERPROC );
void KillTimer( HWND, int id );
#endif
#ifdef WASABI_COMPILE_WND
void TranslateMessage( MSG * );
void PostMessage( HWND, UINT, WPARAM, LPARAM );
void PostQuitMessage( int );
enum contextdata {
GWL_HINSTANCE = 0,
GWL_USERDATA,
GWL_INVALIDREGION,
GWL_RECT_LEFT,
GWL_RECT_TOP,
GWL_RECT_RIGHT,
GWL_RECT_BOTTOM,
GWL_HWND,
GWL_PARENT,
GWL_ENUM_SIZE
};
void MoveWindowRect( HWND, int, int );
void SetWindowRect( HWND, RECT * );
int GetWindowRect( HWND, RECT * );
void SetWindowLong( HWND, enum contextdata, LONG );
LONG GetWindowLong( HWND, enum contextdata );
int GetUpdateRect( HWND, RECT *, BOOL );
void GetUpdateRgn( HWND, HRGN, BOOL );
void InvalidateRgn( HWND, HRGN, BOOL );
void InvalidateRect( HWND, const RECT *, BOOL );
void ValidateRgn( HWND, HRGN );
void ValidateRect( HWND, const RECT * );
HWND GetActiveWindow();
HWND WindowFromPoint( POINT p );
#endif
void OutputDebugString( const char *s );
int MulDiv( int m1, int m2, int d );
DWORD GetTickCount();
void Sleep( int ms );
int IntersectRect(RECT *, const RECT *, const RECT *);
void ExitProcess( int ret );
DWORD GetModuleFileName(void *pid, const char *filename, int bufsize);
const char *CharPrev(const char *lpszStart, const char *lpszCurrent);
int SubtractRect( RECT *out, RECT *in1, RECT *in2 );
int EqualRect( RECT *a, RECT *b );
void CopyFile( const char *f1, const char *f2, BOOL b );
#endif

View File

@ -0,0 +1,961 @@
#include <precomp.h>
#include <api/api.h>
#include <api/linux/api_linux.h>
#include <bfc/ptrlist.h>
#include <bfc/string/string.h>
#include <bfc/critsec.h>
#include <bfc/thread.h>
#include <api/application/ipcs.h>
#ifdef WASABI_COMPILE_WND
Display *Linux::display = NULL;
int linux_atoms_loaded = 0;
Atom winamp_msg;
Atom dnd_enter, dnd_position, dnd_status, dnd_leave, dnd_drop, dnd_finished;
Atom dnd_selection, dnd_wa3drop, dnd_private, dnd_typelist;
Atom dnd_urilist, dnd_textplain, dnd_mozurl;
#endif
#ifndef _NOSTUDIO
#ifdef WASABI_COMPILE_WND
void LoadAtoms() {
if ( !linux_atoms_loaded ) {
linux_atoms_loaded = 1;
winamp_msg = XInternAtom( Linux::getDisplay(), "Winamp3", False );
dnd_wa3drop = XInternAtom( Linux::getDisplay(), "Winamp3_drop", False );
dnd_enter = XInternAtom( Linux::getDisplay(), "XdndEnter", True );
dnd_position = XInternAtom( Linux::getDisplay(), "XdndPosition", True );
dnd_status = XInternAtom( Linux::getDisplay(), "XdndStatus", True );
dnd_leave = XInternAtom( Linux::getDisplay(), "XdndLeave", True );
dnd_drop = XInternAtom( Linux::getDisplay(), "XdndDrop", True );
dnd_finished = XInternAtom( Linux::getDisplay(), "XdndFinished", True );
dnd_selection = XInternAtom( Linux::getDisplay(), "XdndSelection", True );
dnd_private = XInternAtom( Linux::getDisplay(), "XdndActionPrivate", True );
dnd_typelist = XInternAtom( Linux::getDisplay(), "XdndTypeList", True );
dnd_urilist = XInternAtom( Linux::getDisplay(), "text/uri-list", True );
dnd_textplain = XInternAtom( Linux::getDisplay(), "text/plain", True );
dnd_mozurl = XInternAtom( Linux::getDisplay(), "text/x-moz-url", True );
}
}
#endif
#endif
void OutputDebugString( const char *s ) {
#ifdef _DEBUG
fprintf( stderr, "%s", s );
#endif
char *file = getenv( "WASABI_LOG_FILE" );
if ( file ) {
if ( !STRCMP( file, "-" ) ) {
fprintf( stdout, "%s", s );
} else {
FILE *f = fopen( file, "a" );
if ( f ) {
fprintf( f, "%s", s );
fclose( f );
}
}
}
}
DWORD GetTickCount() {
static int starttime = -1;
if ( starttime == -1 )
starttime = time( NULL );
struct timeb tb;
ftime( &tb );
tb.time -= starttime;
return tb.time * 1000 + tb.millitm;
}
void Sleep( int ms ) {
if ( ms != 0 ) {
struct timespec ts = { 0, 0 };
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep( &ts, NULL);
// usleep(ms * 1000);
}
}
#ifndef _NOSTUDIO
#ifdef WASABI_COMPILE_WND
Display *Linux::getDisplay() {
if ( ! display )
display = WASABI_API_LINUX->linux_getDisplay();
return display;
}
XContext Linux::getContext() {
static XContext context = 0;
if ( context == 0 )
context = WASABI_API_LINUX->linux_getContext();
return context;
}
int Linux::getScreenNum() { return DefaultScreen( getDisplay() ); }
Window Linux::RootWin() {
return RootWindow( getDisplay(), getScreenNum() );
}
Visual *Linux::DefaultVis() {
return DefaultVisual( getDisplay(), getScreenNum() );
}
void Linux::setCursor( HWND h, int cursor ) {
Cursor c = XCreateFontCursor( Linux::getDisplay(), cursor );
if ( cursor == None )
XUndefineCursor( Linux::getDisplay(), h );
else
XDefineCursor( Linux::getDisplay(), h, c );
XFreeCursor( Linux::getDisplay(), c );
}
int Linux::convertEvent( MSG *m, XEvent *e ) {
m->hwnd = e->xany.window;
if ( m->hwnd ) {
api_window *rw =(api_window *)GetWindowLong( m->hwnd, GWL_USERDATA );
if ( !rw ) {
// This is to fix messages for dead windows...
return 0;
}
}
switch ( e->type ) {
case ButtonPress:
switch( e->xbutton.button ) {
case 1:
m->message = WM_LBUTTONDOWN;
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
case 2:
case 3:
m->message = WM_RBUTTONDOWN;
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
case 4:
m->message = WM_MOUSEWHEEL;
m->wParam = 120 << 16 | 0; // 1 tick, no modifiers
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
case 5:
m->message = WM_MOUSEWHEEL;
m->wParam = (-120) << 16 | 0; // 1 tick, no modifiers
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
}
break;
case ButtonRelease:
switch( e->xbutton.button ) {
case 1:
m->message = WM_LBUTTONUP;
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
case 2:
case 3:
m->message = WM_RBUTTONUP;
m->lParam = (e->xbutton.x & 0xffff) | (e->xbutton.y << 16);
break;
}
break;
case MotionNotify:
{
m->message = WM_MOUSEMOVE;
do {
// Spin...
} while( XCheckTypedWindowEvent( Linux::getDisplay(), m->hwnd, MotionNotify, e ) );
RECT r;
POINT offset = {0, 0};
HWND hwnd = m->hwnd;
GetWindowRect( hwnd, &r );
m->lParam = ((e->xmotion.x_root - r.left) & 0xffff) |
((e->xmotion.y_root - r.top) << 16);
if ( ! (e->xmotion.state & ( Button1Mask | Button2Mask | Button3Mask )) )
PostMessage( m->hwnd, WM_SETCURSOR, m->hwnd, 0 );
}
break;
case KeyPress:
m->message = WM_KEYDOWN;
m->wParam = e->xkey.keycode;
break;
case KeyRelease:
m->message = WM_KEYUP;
m->wParam = e->xkey.keycode;
break;
case Expose:
{
RECT r;
m->message = WM_PAINT;
do {
r.left = e->xexpose.x;
r.top = e->xexpose.y;
r.right = r.left + e->xexpose.width;
r.bottom = r.top + e->xexpose.height;
InvalidateRect( m->hwnd, &r, FALSE );
} while( XCheckTypedWindowEvent( Linux::getDisplay(), m->hwnd, Expose, e ) );
}
break;
case ClientMessage: {
static int coord = -1;
static Atom supported = None;
XClientMessageEvent cme;
LoadAtoms();
int message = e->xclient.message_type;
if ( message == dnd_enter ) {
if ( e->xclient.data.l[1] & 1 ) {
Atom actual;
int format;
long unsigned int nitems, bytes;
unsigned char *data = NULL;
XGetWindowProperty( Linux::getDisplay(), e->xclient.data.l[0],
dnd_typelist, 0, 65536, True, XA_ATOM,
&actual, &format, &nitems, &bytes, &data );
Atom *atomdata = (Atom *)data;
supported = None;
for( int i = 0; i < nitems; i++ ) {
if ( atomdata[i] == dnd_urilist ) {
supported = dnd_urilist;
}
}
if ( supported == None ) {
for( int i = 0; i < nitems; i++ ) {
if ( atomdata[i] == dnd_textplain ) {
OutputDebugString( "text/plain found\n" );
supported = dnd_textplain;
}
}
}
if ( supported == None ) {
for( int i = 0; i < nitems; i++ ) {
if ( atomdata[i] == dnd_mozurl ) {
supported = dnd_mozurl;
}
}
}
XFree( data );
} else {
if ( e->xclient.data.l[2] == dnd_urilist ||
e->xclient.data.l[3] == dnd_urilist ||
e->xclient.data.l[4] == dnd_urilist ) {
supported = dnd_urilist;
} else if ( e->xclient.data.l[2] == dnd_mozurl ||
e->xclient.data.l[3] == dnd_mozurl ||
e->xclient.data.l[4] == dnd_mozurl ) {
supported = dnd_mozurl;
}
}
// DnD Enter
return 0;
} else if ( message == dnd_position ) {
// DnD Position Notify
cme.type = ClientMessage;
cme.message_type = dnd_status;
cme.format = 32;
cme.window = e->xclient.data.l[0];
cme.data.l[0] = e->xclient.window;
cme.data.l[1] = 1; // Can Accept
cme.data.l[2] = cme.data.l[3] = 0; // Empty rectangle - give us moves
cme.data.l[4] = dnd_private; // We're doing our own thing
if ( coord == -1 && supported != None ) {
XConvertSelection( Linux::getDisplay(), dnd_selection, supported,
dnd_wa3drop, cme.window, CurrentTime );
}
coord = e->xclient.data.l[2];
XSendEvent( Linux::getDisplay(), e->xclient.data.l[0], False,
NoEventMask, (XEvent *)&cme );
return 0;
} else if ( message == dnd_leave ) {
// DnD Leave
coord = -1;
supported = None;
return 0;
} else if ( message == dnd_drop ) {
// DnD Drop
Window win = e->xclient.data.l[0];
cme.type = ClientMessage;
cme.message_type = dnd_finished;
cme.format = 32;
cme.window = e->xclient.data.l[0];
cme.data.l[0] = e->xclient.window;
cme.data.l[1] = cme.data.l[2] = cme.data.l[3] = cme.data.l[4] = 0;
XSendEvent( Linux::getDisplay(), e->xclient.data.l[0], False,
NoEventMask, (XEvent *)&cme );
if ( supported != None ) {
Atom actual;
int format;
long unsigned int nitems, bytes;
unsigned char *data = NULL;
XGetWindowProperty( Linux::getDisplay(), cme.window, dnd_wa3drop,
0, 65536, True, supported, &actual,
&format, &nitems, &bytes,
&data );
OutputDebugString( StringPrintf( "Drop data (%d):\n%s\n", nitems, data ) );
m->message = WM_DROPFILES;
m->wParam = coord;
m->lParam = (LPARAM)data;
coord = -1;
supported = None;
} else {
coord = -1;
supported = None;
return 0;
}
break;
} else if ( message == winamp_msg ) {
// Internal Message ...
m->message = e->xclient.data.l[0];
m->wParam = e->xclient.data.l[1];
m->lParam = e->xclient.data.l[2];
break;
} else {
return 0;
}
break;
}
case LeaveNotify:
case EnterNotify:
m->message = WM_MOUSEMOVE;
m->lParam = (e->xcrossing.x & 0xffff) | (e->xcrossing.y << 16);
if ( ! (e->xcrossing.state & ( Button1Mask | Button2Mask | Button3Mask )) )
PostMessage( m->hwnd, WM_SETCURSOR, m->hwnd, 0 );
break;
case FocusIn:
m->message = WM_SETFOCUS;
break;
case FocusOut:
m->message = WM_KILLFOCUS;
break;
default:
return 0;
}
return 1;
}
static HWND activeWindow;
HWND GetActiveWindow() {
return activeWindow;
}
int IntersectRect( RECT *out, const RECT *i1, const RECT *i2 ) {
return Std::rectIntersect(i1, i2, out);
}
void TranslateMessage( MSG *m ) {
if ( m->message != WM_CHAR && m->message != WM_KEYDOWN &&
m->message != WM_KEYUP )
return;
int index = !!( Std::keyDown( VK_SHIFT ));
m->wParam = XKeycodeToKeysym( Linux::getDisplay(), m->wParam, index );
}
void PostMessage( HWND win, UINT msg, WPARAM wParam, LPARAM lParam ) {
XEvent e;
LoadAtoms();
e.type = ClientMessage;
e.xclient.window = win;
e.xclient.message_type = winamp_msg;
e.xclient.format = 32;
e.xclient.data.l[0] = msg;
e.xclient.data.l[1] = wParam;
e.xclient.data.l[2] = lParam;
XSendEvent( Linux::getDisplay(), win, FALSE, NoEventMask, &e );
}
void PostQuitMessage( int i ) {
PostMessage( None, WM_QUIT, i, 0 );
}
#endif // wnd
#if defined(WASABI_API_TIMER) | defined(WASABI_API_WND)
struct TimerElem {
HWND win;
int id;
int nexttime;
int delta;
TIMERPROC tproc;
TimerElem( HWND _win, int _id, int ms, TIMERPROC _tproc ) {
win = _win;
id = _id;
delta = ms;
tproc = _tproc;
nexttime = Std::getTickCount() + delta;
}
};
int timer_id = 0;
CriticalSection timer_cs;
PtrList<TimerElem> timer_elems;
int SetTimer( HWND win, int id, int ms, TIMERPROC tproc ) {
KillTimer(win, id);
if ( win == (HWND)0 ) {
id = timer_id++;
}
TimerElem *te = new TimerElem( win, id, ms, tproc );
timer_cs.enter();
timer_elems.addItem( te, PTRLIST_POS_LAST );
timer_cs.leave();
return id;
}
void KillTimer( HWND win, int id ) {
timer_cs.enter();
for( int i = 0; i < timer_elems.getNumItems(); i++ )
if ( timer_elems[i]->win == win && timer_elems[i]->id == id ) {
delete timer_elems[i];
timer_elems.delByPos( i );
i--;
}
timer_cs.leave();
}
CriticalSection send_cs;
MSG *send_msg;
int sending = 0;
int send_ret;
pthread_t message_thread = (pthread_t)-1;
int _GetMessage( MSG *m, HWND, UINT, UINT, int block=1) {
MEMSET( m, 0, sizeof( MSG ) );
message_thread = pthread_self();
#ifdef WASABI_COMPILE_WND
XEvent e;
#endif // wnd
int curtime;
int done = 0;
int first = 1;
static wa_msgbuf ipcm;
static int qid = -1;
int size;
if ( qid == -1 ) { qid = WASABI_API_LINUX->linux_getIPCId(); }
if ( sending ) {
*m = *send_msg;
done = 1;
}
while( !done && (block || first)) {
if ( qid != -1 ) {
if ( (size = msgrcv( qid, &ipcm, IPC_MSGMAX , 0, IPC_NOWAIT )) != -1 ) {
m->hwnd = None;
m->message = WM_WA_IPC;
m->wParam = (WPARAM)&ipcm;
break;
}
}
curtime = GetTickCount();
timer_cs.enter();
for( int i = 0; i < timer_elems.getNumItems(); i++ ) {
if ( timer_elems[i]->nexttime < curtime ) {
if (block)
while( timer_elems[i]->nexttime < curtime )
timer_elems[i]->nexttime += timer_elems[i]->delta;
m->hwnd = timer_elems[i]->win;
m->message = WM_TIMER;
m->wParam = (WPARAM)timer_elems[i]->id;
m->lParam = (LPARAM)timer_elems[i]->tproc;
done = 1;
}
}
timer_cs.leave();
if ( !done && ! first )
Sleep( 1 );
else
first = 0;
#ifdef WASABI_API_WND
if ( !done && XPending( Linux::getDisplay() ) ) {
int n = XEventsQueued( Linux::getDisplay(), QueuedAlready );
for ( int i = 0; !done && i < n; i++ ) {
XNextEvent( Linux::getDisplay(), &e );
if ( Linux::convertEvent( m, &e ) )
done = 1;
}
if ( done )
break;
}
#endif // wnd
}
#ifdef WASABI_API_WND
activeWindow = m->hwnd;
#endif // wnd
return m->message != WM_QUIT;
}
int GetMessage( MSG *m, HWND w, UINT f, UINT l) {
return _GetMessage(m, w, f, l, 1);
}
// on linux, we don't really simply peek when PM_NOREMOVE is used,
// we just don't block, which is the only thing we want to accomplish here
int PeekMessage( MSG *m, HWND w, UINT f, UINT l, UINT remove) {
if (remove == PM_NOREMOVE) return _GetMessage(m, w, f, l, 0);
else _GetMessage(m, w, f, l, 1);
}
int DispatchMessage( MSG *m ) {
if ( m->message == WM_TIMER && m->hwnd == None ) {
TIMERPROC tproc = (TIMERPROC)m->lParam;
tproc( m->hwnd, m->message, m->wParam, 0 );
return 1;
}
int ret = 0;
#ifdef WASABI_COMPILE_WND
api_window *rootwnd = (api_window *)GetWindowLong( m->hwnd, GWL_USERDATA );
if ( rootwnd ) {
ret = rootwnd->wndProc( m->hwnd, m->message, m->wParam, m->lParam );
rootwnd->performBatchProcesses();
}
#endif // wnd
if ( sending ) {
send_ret = ret;
sending = 0;
}
return ret;
}
int SendMessage( HWND win, UINT msg, WPARAM wParam, LPARAM lParam ) {
MSG m;
m.hwnd = win;
m.message = msg;
m.wParam = wParam;
m.lParam = lParam;
int ret;
if ( pthread_equal( message_thread, pthread_self() ) ) {
return DispatchMessage( &m );
} else {
send_cs.enter();
sending = 1;
send_msg = &m;
while( sending ) { Sleep( 1 ); }
ret = send_ret;
send_cs.leave();
return ret;
}
}
#endif // timer | wnd
int MulDiv( int m1, int m2, int d ) {
__asm__ volatile (
"mov %0, %%eax\n"
"mov %1, %%ebx\n"
"mov %2, %%ecx\n"
"mul %%ebx\n"
"div %%ecx\n"
: : "m" (m1), "m" (m2), "m" (d)
: "%eax", "%ebx", "%ecx", "%edx" );
}
void ExitProcess( int ret ) {
exit( ret );
}
#ifdef WASABI_COMPILE_WND
void Linux::initContextData( HWND h ) {
int *data;
XPointer xp;
ASSERT( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ));
data = (int *)MALLOC( GWL_ENUM_SIZE * sizeof( int ) );
data[GWL_HWND] = h;
XSaveContext( Linux::getDisplay(), h, Linux::getContext(), (char *)data );
}
void Linux::nukeContextData( HWND h ) {
int *data;
XPointer xp;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
return;
data = (int *)xp;
ASSERT( data[GWL_HWND] == h );
if ( data[GWL_INVALIDREGION] ) {
XDestroyRegion( (HRGN)data[GWL_INVALIDREGION] );
}
XDeleteContext( Linux::getDisplay(), h, Linux::getContext() );
FREE( data );
}
void SetWindowLong( HWND h, contextdata type, LONG value ) {
XPointer data;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &data ) )
return;
ASSERT( ((int *)data)[GWL_HWND] == h );
((int*)data)[type] = value;
}
LONG GetWindowLong( HWND h, contextdata type ) {
XPointer data;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &data ) )
return 0;
ASSERT( ((int *)data)[GWL_HWND] == h );
return ((int*)data)[type];
}
void MoveWindowRect( HWND h, int x, int y ) {
XPointer xp;
int *data;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
return;
data = (int *)xp;
ASSERT( data[GWL_HWND] == h );
data[GWL_RECT_RIGHT] -= data[GWL_RECT_LEFT] - x;
data[GWL_RECT_BOTTOM] -= data[GWL_RECT_TOP] - y;
data[GWL_RECT_LEFT] = x;
data[GWL_RECT_TOP] = y;
}
void SetWindowRect( HWND h, RECT *r ) {
int *data;
XPointer xp;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
return;
data = (int *)xp;
ASSERT( data[GWL_HWND] == h );
data[GWL_RECT_LEFT] = r->left;
data[GWL_RECT_TOP] = r->top;
data[GWL_RECT_RIGHT] = r->right;
data[GWL_RECT_BOTTOM] = r->bottom;
}
int GetWindowRect( HWND h, RECT *r ) {
int *data;
XPointer xp;
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
return 0;
data = (int *)xp;
ASSERT( data[GWL_HWND] == h );
r->left = data[GWL_RECT_LEFT];
r->top = data[GWL_RECT_TOP];
r->right = data[GWL_RECT_RIGHT];
r->bottom = data[GWL_RECT_BOTTOM];
POINT offset = { 0, 0};
while( (h = data[GWL_PARENT]) != Linux::RootWin() ) {
if ( XFindContext( Linux::getDisplay(), h, Linux::getContext(), &xp ) )
return 0;
data = (int *)xp;
ASSERT( data[GWL_HWND] == h );
offset.x += data[GWL_RECT_LEFT];
offset.y += data[GWL_RECT_TOP];
}
r->left += offset.x;
r->top += offset.y;
r->right += offset.x;
r->bottom += offset.y;
return 1;
}
int GetUpdateRect( HWND h, RECT *ret, BOOL ) {
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid || XEmptyRegion( invalid ) )
return 0;
XRectangle xr;
XClipBox( invalid, &xr );
ret->left = xr.x;
ret->top = xr.y;
ret->right = xr.x + xr.width;
ret->bottom = xr.y + xr.height;
return 1;
}
void GetUpdateRgn( HWND h, HRGN r, BOOL ) {
XSubtractRegion( r, r, r );
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid ) return;
XUnionRegion( r, invalid, r );
XRectangle xr;
RECT rct;
GetWindowRect( h, &rct );
xr.x = 0;
xr.y = 0;
xr.width = rct.right - rct.left;
xr.height = rct.bottom - rct.top;
HRGN tmp = XCreateRegion();
XUnionRectWithRegion( &xr, tmp, tmp );
XIntersectRegion( r, tmp, r );
XDestroyRegion( tmp );
}
void InvalidateRect( HWND h, const RECT *r, BOOL ) {
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid ) {
invalid = XCreateRegion();
SetWindowLong( h, GWL_INVALIDREGION, (LONG)invalid );
}
XRectangle xr;
if ( r == NULL ) {
RECT rct;
GetWindowRect( h, &rct );
xr.x = 0;
xr.y = 0;
xr.width = rct.right - rct.left;
xr.height = rct.bottom - rct.top;
} else {
xr.x = r->left;
xr.y = r->top;
xr.width = r->right - r->left;
xr.height = r->bottom - r->top;
}
XUnionRectWithRegion( &xr, invalid, invalid );
PostMessage( h, WM_PAINT, 0, 0 );
}
void InvalidateRgn( HWND h, HRGN r, BOOL ) {
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid ) {
invalid = XCreateRegion();
SetWindowLong( h, GWL_INVALIDREGION, (LONG)invalid );
}
ASSERT( r != invalid );
XUnionRegion( invalid, r, invalid );
PostMessage( h, WM_PAINT, 0, 0 );
}
void ValidateRect( HWND h, const RECT *r ) {
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid ) return;
XRectangle xr;
if ( r == NULL ) {
XDestroyRegion( invalid );
SetWindowLong( h, GWL_INVALIDREGION, 0 );
return;
}
xr.x = r->left;
xr.y = r->top;
xr.width = r->right - r->left;
xr.height = r->bottom - r->top;
HRGN tmp = XCreateRegion();
XUnionRectWithRegion( &xr, tmp, tmp );
XSubtractRegion( invalid, tmp, invalid );
XDestroyRegion( tmp );
}
void ValidateRgn( HWND h, HRGN r ) {
HRGN invalid = (HRGN)GetWindowLong( h, GWL_INVALIDREGION );
if ( ! invalid ) return;
ASSERT( r != invalid );
XSubtractRegion( invalid, r, invalid );
}
#endif // wnd
int SubtractRect( RECT *out, RECT *in1, RECT *in2 ) {
int ret;
if ( in1->left >= in2->left && in1->right <= in2->right ) {
out->left = in1->left; out->right = in1->right;
if ( in1->top >= in2->top && in2->bottom >= in2->top && in2->bottom <= in2->bottom ) {
out->top = in1->bottom; out->bottom = in2->bottom;
ret = 1;
} else if ( in1->top <= in2->top && in1->bottom >= in2->top && in1->bottom <= in2->bottom ) {
out->top = in1->top; out->bottom = in2->top;
ret = 1;
} else {
ret = 0;
}
} else if ( in1->top >= in2->top && in1->bottom <= in2->bottom ) {
out->top = in1->top; out->bottom = in1->bottom;
if ( in1->left >= in2->left && in2->right >= in2->left && in2->right <= in2->right ) {
out->left = in1->right; out->right = in2->right;
ret = 1;
} else if ( in1->left <= in2->left && in1->right >= in2->left && in1->right <= in2->right ) {
out->left = in1->left; out->right = in2->left;
ret = 1;
} else {
ret = 0;
}
} else {
ret = 0;
}
return ret;
}
int EqualRect( RECT *a, RECT *b ) {
return ( a->top == b->top && a->bottom == b->bottom &&
a->left == b->left && a->right == b->right );
}
#ifdef WASABI_COMPILE_WND
HWND WindowFromPoint( POINT p ) {
int x, y;
Window child;
XTranslateCoordinates( Linux::getDisplay(), Linux::RootWin(), Linux::RootWin(), p.x, p.y, &x, &y, &child );
return child;
}
#endif // wnd
void CopyFile( const char *f1, const char *f2, BOOL b ) {
COPYFILE( f1, f2 );
}
DWORD GetModuleFileName(void *pid, const char *filename, int bufsize) {
char procbuffer[512];
sprintf(procbuffer, "/proc/%d/exe", (int)pid);
return readlink(procbuffer, (char *)filename, bufsize);
}
const char *CharPrev(const char *lpszStart, const char *lpszCurrent) {
if (lpszCurrent-1 >= lpszStart) return lpszCurrent-1;
return lpszStart;
}
#endif

View File

@ -0,0 +1,19 @@
#ifndef NULLSOFT_BFC_PLATFORM_MINMAX_H
#define NULLSOFT_BFC_PLATFORM_MINMAX_H
#if defined(_WIN32) && !defined(MIN)
#define MIN( a, b ) ((a>b)?b:a)
#define MAX( a, b ) ((a>b)?a:b)
#endif
#if defined(__APPLE__) && !defined(MIN)
#define MIN( a, b ) ((a>b)?b:a)
#define MAX( a, b ) ((a>b)?a:b)
#endif
#if defined(__linux__) && !defined(MIN)
#define MIN( a, b ) ((a>b)?b:a)
#define MAX( a, b ) ((a>b)?a:b)
#endif
#endif

View File

@ -0,0 +1,6 @@
#include "precomp_wasabi_bfc.h"
#include "platform.h"
void link_platform() {
OutputDebugString(L"dummy");
}

View File

@ -0,0 +1,498 @@
#pragma once
#include <bfc/platform/types.h>
#include <bfc/std_mkncc.h> // for MKnCC
#ifdef WIN32
# include <bfc/platform/win32.h>
#define OSMODULEHANDLE HINSTANCE
#define INVALIDOSMODULEHANDLE ((OSMODULEHANDLE)0)
#define OSWINDOWHANDLE HWND
#define INVALIDOSWINDOWHANDLE ((OSWINDOWHANDLE)0)
#define OSICONHANDLE HICON
#define INVALIDOSICONHANDLE ((OSICONHANDLE)0)
#define OSCURSORHANDLE HICON
#define INVALIDOSCURSORHANDLE ((OSCURSORHANDLE)0)
#define OSTHREADHANDLE HANDLE
#define INVALIDOSTHREADHANDLE ((OSTHREADHANDLE)0)
#define OSREGIONHANDLE HRGN
#define INVALIDOSREGIONHANDLE ((OSREGIONHANDLE)0)
typedef HMENU OSMENUHANDLE;
#define RGBA(r,g,b,a) ((ARGB32)((uint8_t)(r) | ((uint8_t)(g) << 8) | ((uint8_t)(b) << 16) | ((uint8_t)(a) << 24)))
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#elif defined(LINUX)
# include <bfc/platform/linux.h>
#elif defined(__APPLE__)
#include <Carbon/Carbon.h>
typedef HIShapeRef OSREGIONHANDLE;
typedef int OSCURSOR; // TODO: find a good one for this
typedef int OSCURSORHANDLE; // TODO: find a good one for this
typedef HIWindowRef OSWINDOWHANDLE;
typedef void *OSMODULEHANDLE; // TODO:
typedef CGContextRef HDC; // TODO: find a better name
typedef MenuRef OSMENUHANDLE;
typedef CGImageRef OSICONHANDLE;
#ifdef __LITTLE_ENDIAN__
#define RGBA(r,g,b,a) ((ARGB32)((uint8_t)(r) | ((uint8_t)(g) << 8) | ((uint8_t)(b) << 16) | ((uint8_t)(a) << 24)))
#elif defined(__BIG_ENDIAN__)
#define RGBA(r,g,b,a) ((ARGB32)((uint8_t)(a) | ((uint8_t)(r) << 8) | ((uint8_t)(g) << 16) | ((uint8_t)(b) << 24)))
#else
#error endian preprocessor symbol not defined
#endif
#define RGB(r,g,b) RGBA(r,g,b,0xFF)
static const HIWindowRef INVALIDOSWINDOWHANDLE = 0; // TODO: maybe there's an apple-defined name for this
#define INVALIDOSMODULEHANDLE 0
#define INVALIDOSCURSORHANDLE 0
typedef char OSFNCHAR;
typedef char *OSFNSTR;
typedef const char OSFNCCHAR;
typedef const char *OSFNCSTR;
#define FNT(x) x
typedef struct tagRECT
{
int left;
int top;
int right;
int bottom;
}
RECT;
typedef RECT * LPRECT;
inline RECT RECTFromHIRect(const HIRect *r)
{
RECT rect;
rect.left = r->origin.x;
rect.right = r->origin.x + r->size.width;
rect.top = r->origin.y;
rect.bottom = r->origin.y + r->size.height;
return rect;
}
inline HIRect HIRectFromRECT(const RECT *r)
{
HIRect rect;
rect.origin.x = r->left;
rect.origin.y = r->top;
rect.size.width = r->right - r->left;
rect.size.height = r->bottom - r->top;
return rect;
}
typedef struct tagPOINT
{
int x;
int y;
}
POINT;
typedef struct tagPOINT * LPPOINT;
inline HIPoint HIPointFromPOINT(const POINT *pt)
{
HIPoint p;
p.x = pt->x;
p.y = pt->y;
return p;
}
inline int MulDiv(int a, int b, int c)
{
int s;
int v;
s = 0;
if (a < 0)
{
s = !s;
a = -a;
}
if (b < 0)
{
s = !s;
b = -b;
}
if (c < 0)
{
s = !s;
c = -c;
}
double d;
d = ((double)a * (double)b) / (double)c;
if (d >= 4294967296.)
return -1;
v = d;
if (s)
v = -v;
return v;
}
#else
#error port me
// Windows API dependant definitions for non-windows platforms
#define __cdecl
#define __stdcall
#define WINAPI
#define WINBASEAPI
#define WINUSERAPI
#define WINGDIAPI
#define WINOLEAPI
#define CALLBACK
#define FARPROC void *
#define FALSE 0
#define TRUE 1
#define ERROR 0
#define CONST const
#define VOID void
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef long LONG;
typedef int INT;
typedef int BOOL;
typedef short SHORT;
typedef void * PVOID;
typedef void * LPVOID;
typedef char CHAR;
typedef unsigned short WCHAR;
typedef char * LPSTR;
typedef WCHAR * LPWSTR;
typedef const char * LPCSTR;
typedef const WCHAR * LPCWSTR;
typedef LPWSTR PTSTR, LPTSTR;
typedef LPCWSTR LPCTSTR;
typedef char TCHAR;
typedef WCHAR OLECHAR;
typedef void * HANDLE;
typedef void * HWND;
typedef void * HDC;
typedef void * HFONT;
typedef void * HBITMAP;
typedef void * HINSTANCE;
typedef void * HICON;
typedef void * HRGN;
typedef void * HPEN;
typedef void * HBRUSH;
typedef void * HRSRC;
typedef void * HGLOBAL;
typedef void * HACCEL;
typedef void * HMODULE;
typedef void * HMENU;
typedef void * HGDIOBJ;
typedef void * ATOM;
typedef void * CRITICAL_SECTION;
typedef void * LPCRITICAL_SECTION;
typedef UINT WPARAM;
typedef UINT LPARAM;
typedef LONG LRESULT;
typedef UINT COLORREF;
typedef LRESULT(*WNDPROC)(HWND, UINT, WPARAM, LPARAM);
typedef BOOL CALLBACK WNDENUMPROC(HWND, LPARAM);
typedef VOID CALLBACK *TIMERPROC(HWND, UINT, UINT, DWORD);
typedef struct tagPOINT
{
LONG x;
LONG y;
}
POINT;
typedef struct tagPOINT * LPPOINT;
typedef struct tagSIZE
{
LONG cx;
LONG cy;
}
SIZE;
typedef struct tagRECT
{
LONG left;
LONG top;
LONG right;
LONG bottom;
}
RECT;
typedef RECT * LPRECT;
typedef struct _COORD
{
SHORT X;
SHORT Y;
}
COORD, *PCOORD;
typedef struct tagPAINTSTRUCT
{
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
}
PAINTSTRUCT;
typedef struct tagBITMAP
{ /* bm */
int bmType;
int bmWidth;
int bmHeight;
int bmWidthBytes;
BYTE bmPlanes;
BYTE bmBitsPixel;
LPVOID bmBits;
}
BITMAP;
typedef struct tagRGBQUAD
{
BYTE rgbRed;
BYTE rgbGreen;
BYTE rgbBlue;
BYTE rgbReserved;
}
RGBQUAD;
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}
BITMAPINFOHEADER;
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
}
BITMAPINFO, *LPBITMAPINFO;
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}
MSG;
typedef MSG * LPMSG;
typedef struct _RGNDATAHEADER
{
DWORD dwSize;
DWORD iType;
DWORD nCount;
DWORD nRgnSize;
RECT rcBound;
}
RGNDATAHEADER, *PRGNDATAHEADER;
typedef struct _RGNDATA
{
RGNDATAHEADER rdh;
char Buffer[1];
}
RGNDATA, *PRGNDATA;
// Windows messages
#define WM_SYSCOMMAND 0x112
#define WM_LBUTTONDOWN 0x201
#define WM_LBUTTONUP 0x202
#define WM_RBUTTONDOWN 0x204
#define WM_RBUTTONUP 0x205
#define WM_USER 0x400
#define WS_EX_TOOLWINDOW 0x00000080L
#define WS_OVERLAPPED 0x00000000L
#define WS_MAXIMIZEBOX 0x00010000L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_SYSMENU 0x00080000L
#define WS_CAPTION 0x00C00000L
#define WS_CLIPCHILDREN 0x02000000L
#define WS_CLIPSIBLINGS 0x04000000L
#define WS_VISIBLE 0x10000000L
#define WS_CHILD 0x40000000L
#define WS_POPUP 0x80000000L
#define HWND_TOP ((HWND)0)
#define HWND_TOPMOST ((HWND)-1)
#define HWND_NOTOPMOST ((HWND)-2)
#define GWL_STYLE (-16)
#define GW_HWNDFIRST 0
#define GW_HWNDNEXT 2
#define SWP_NOMOVE 0x0002
#define SWP_NOSIZE 0x0001
#define SWP_SHOWWINDOW 0x0040
#define SWP_DEFERERASE 0x2000
#define SWP_NOZORDER 0x0004
#define SWP_NOACTIVATE 0x0010
#define SW_SHOW 5
#define SC_MINIMIZE 0xF020
#define SC_MAXIMIZE 0xF030
#define SC_RESTORE 0xF120
#define GCL_HICONSM (-34)
#define GCL_HICON (-14)
#define MB_OK 0
#define MB_OKCANCEL 1
#define MB_TASKMODAL 0x2000L
#define IDOK 1
#define IDCANCEL 2
#define VK_SHIFT 0x10
#define VK_CONTROL 0x11
#define VK_MENU 0x12
#define RT_RCDATA 10
#define IMAGE_BITMAP 0
#define LR_LOADFROMFILE 0x0010
#define DIB_RGB_COLORS 0
#define MAX_PATH 1024
#define _MAX_PATH MAX_PATH
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#define _MAX_FNAME 256
#define _MAX_EXT 256
#define GMEM_FIXED 0x0
#define GMEM_ZEROINIT 0x40
#define GPTR (GMEM_FIXED | GMEM_ZEROINIT)
#define SPI_GETWORKAREA 48
#define SM_CXDOUBLECLK 36
#define SM_CYDOUBLECLK 37
#define COLORONCOLOR 3
#define SRCCOPY (DWORD)0x00CC0020
#define BI_RGB 0L
#define NULLREGION 1
#define DT_LEFT 0x00000000
#define DT_CENTER 0x00000001
#define DT_RIGHT 0x00000002
#define DT_VCENTER 0x00000004
#define DT_WORDBREAK 0x00000010
#define DT_SINGLELINE 0x00000020
#define DT_CALCRECT 0x00000400
#define DT_NOPREFIX 0x00000800
#define DT_PATH_ELLIPSIS 0x00004000
#define DT_END_ELLIPSIS 0x00008000
#define DT_MODIFYSTRING 0x00010000
#define FW_NORMAL 400
#define FW_BOLD 700
#define FF_DONTCARE (0<<4)
#define BLACK_BRUSH 4
#define NULL_BRUSH 5
#define PS_SOLID 0
#define PS_DOT 2
#define TRANSPARENT 1
#define OPAQUE 2
#define ANSI_CHARSET 0
#define ANSI_VAR_FONT 12
#define OUT_DEFAULT_PRECIS 0
#define CLIP_DEFAULT_PRECIS 0
#define PROOF_QUALITY 2
#define VARIABLE_PITCH 2
#define RGN_AND 1
#define RGN_OR 2
#define RGN_DIFF 4
#define RGN_COPY 5
#define RDH_RECTANGLES 1
#define MAXLONG 0x7fffffff
// define GUID
#include <bfc/platform/guid.h>
#endif /* not WIN32 */
#include <stdio.h>
#include <stdlib.h>
//#ifdef __cplusplus
//#include <new>
//#else
//#include <new.h>
//#endif
#include <limits.h>
#ifdef WIN32
#define OSPIPE HANDLE
#define OSPROCESSID int
#endif
// Ode macro keyworkds
#define DISPATCH_ // makes a method dispatchable, automatically assigns a free ID (requires Interface)
#define DISPATCH(x) // makes a method dispatchable and specifies its ID (not duplicate check, requires Interface)
#define NODISPATCH // prevents a method from being dispatched if the class is marked for dispatching by default
#define EVENT // marks a method as being an event to which other classes can connect to receive notification (used by Script and DependentItem helpers)
#define SCRIPT // exposes a method to script interfaces (requires Script helper)
#define IN // Input parameter
#define OUT // Output parameter
#define INOUT // Input/Output parameter

View File

@ -0,0 +1,246 @@
#include <bfc/std.h>
// not perfect but it should work
int WCSICMP(const wchar_t *str1, const wchar_t *str2)
{
while (*str1 && *str2)
{
if (towlower(*str1) < towlower(*str2))
return -1;
if (towlower(*str2) < towlower(*str1))
return 1;
str1++;
str2++;
}
if (!*str1 && !*str2) return 0;
if (*str1) return 1;
if (*str2) return -1;
return -1; // shouldn't get here but we'll make the compiler shut up
}
int WCSNICMP(const wchar_t *str1, const wchar_t *str2, size_t len)
{
while (*str1 && *str2 && len)
{
if (towlower(*str1) < towlower(*str2))
return -1;
if (towlower(*str2) < towlower(*str1))
return 1;
str1++;
str2++;
len--;
}
if (!len) return 0;
if (!*str1 && !*str2) return 0;
if (*str1) return 1;
if (*str2) return -1;
return -1; // shouldn't get here but we'll make the compiler shut up
}
/* these are super slow because of memory allocation, but will tide us over until apple adds wcscasecmp and family to their BSD API */
#if 0 // remember this if we ever decide to use -fshort-wchar
int WCSICMP(const wchar_t *str1, const wchar_t *str2)
{
CFStringRef cfstr1 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str1, wcslen(str1)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
CFStringRef cfstr2 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str2, wcslen(str2)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
int result = CFStringCompare(cfstr1, cfstr2, kCFCompareCaseInsensitive);
CFRelease(cfstr1);
CFRelease(cfstr2);
return result;
}
int WCSNICMP(const wchar_t *str1, const wchar_t *str2, size_t len)
{
CFStringRef cfstr1 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str1, wcslen(str1)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
CFStringRef cfstr2 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str2, wcslen(str2)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
int result = CFStringCompareWithOptions(cfstr1, cfstr2, CFRangeMake(0, len), kCFCompareCaseInsensitive);
CFRelease(cfstr1);
CFRelease(cfstr2);
return result;
}
#endif
int WCSICOLL(const wchar_t *str1, const wchar_t *str2)
{
CFStringRef cfstr1 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str1, wcslen(str1)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
CFStringRef cfstr2 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str2, wcslen(str2)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
int result = CFStringCompare(cfstr1, cfstr2, kCFCompareCaseInsensitive|kCFCompareNonliteral);
CFRelease(cfstr1);
CFRelease(cfstr2);
return result;
}
bool WCSIPREFIX(const wchar_t *str1, const wchar_t *prefix)
{
CFStringRef cfstr1 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)str1, wcslen(str1)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
CFStringRef cfstr2 = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)prefix, wcslen(prefix)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
bool result = CFStringHasPrefix(cfstr1, cfstr2);
CFRelease(cfstr1);
CFRelease(cfstr2);
return result;
}
wchar_t *DO_WCSDUP(const wchar_t *ptr EXTRA_INFO)
{
if (ptr == NULL) return NULL;
int size = wcslen(ptr);
wchar_t *ret = (wchar_t *)MALLOC((size + 1) * sizeof(wchar_t));
if (ret != NULL)
{
WCSCPYN(ret, ptr, size+1);
}
return ret;
}
void WCSCPYN(wchar_t *dest, const wchar_t *src, int maxchar)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
wcsncpy(dest, src, maxchar-1); // TODO: switch to a less brain dead function
dest[maxchar-1]=0;
}
void STRTOUPPER(char *str)
{
if (str)
{
while (*str)
{
*str = toupper(*str);
}
}
}
void STRTOLOWER(char *str)
{
if (str)
{
while (*str)
{
*str = towlower(*str);
}
}
}
COMEXP void WCSTOUPPER(wchar_t *str)
{
if (str)
{
while (*str)
{
*str = towupper(*str);
}
}
}
COMEXP void WCSTOLOWER(wchar_t *str)
{
if (str)
{
while (*str)
{
*str = towlower(*str);
}
}
}
int WCSICMPSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2)
{
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return WCSICMP(str1, str2);
}
wchar_t *WCSTOK(wchar_t *str, const wchar_t *sep, wchar_t **last)
{
return wcstok(str, sep, last);
}
int WCSCASEEQLSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2)
{
return !WCSICMPSAFE(str1, str2, defval1, defval2);
}
int STRLEN(const char *str)
{
ASSERT(str != NULL);
return strlen(str);
}
bool ISALPHA(wchar_t alpha)
{
return iswalpha(alpha);
}
bool ISDIGIT(wchar_t digit)
{
return iswdigit(digit);
}
bool ISSPACE(wchar_t space)
{
return iswspace(space);
}
bool ISPUNCT(wchar_t punct)
{
return iswpunct(punct);
}
int STRCMP(const char *str1, const char *str2)
{
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
return strcmp(str1, str2);
}
int STRCMPSAFE(const char *str1, const char *str2, const char *defval1, const char *defval2)
{
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return STRCMP(str1, str2);
}
void STRNCPY(char *dest, const char *src, int maxchar)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
strncpy(dest, src, maxchar);
//INLINE
}
int STRICMPSAFE(const char *str1, const char *str2, const char *defval1, const char *defval2)
{
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return STRICMP(str1, str2);
}
int STRICMP(const char *str1, const char *str2)
{
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
return strcasecmp(str1, str2);
}
void STRCPY(char *dest, const char *src)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
ASSERT(dest != src);
strcpy(dest, src);
//INLINE
}
char *STRSTR(const char *str1, const char *str2)
{
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
ASSERT(str1 != str2);
return strstr(str1, str2);
}

View File

@ -0,0 +1,15 @@
#ifndef NULLSOFT_BFC_STRCMP_H
#define NULLSOFT_BFC_STRCMP_H
#ifdef _WIN32
#include <shlwapi.h>
#define strcasestr StrStrIA
#endif
#ifdef __APPLE__
#include <string.h>
#define _strnicmp strncasecmp
#define _stricmp strcasecmp
#endif
#endif

View File

@ -0,0 +1,2 @@
#include <bfc/platform/platform.h>
#include "../replicant/foundation/types.h"

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdio.h>
#ifndef WIN32
#error this file is only for win32
#endif
// this should be the *only* place windows.h gets included!
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifndef _WIN32_WCE
#include <io.h>
#endif
#if defined(_MSC_VER) // msvc
# define WASABIDLLEXPORT __declspec(dllexport)
# if _MSC_VER >= 1100
# define NOVTABLE __declspec(novtable)
# endif
#endif
#define OSPIPE HANDLE
typedef WCHAR OSFNCHAR;
typedef LPWSTR OSFNSTR;
typedef LPCWSTR OSFNCSTR;

View File

@ -0,0 +1 @@
#include "precomp_wasabi_bfc.h"

View File

@ -0,0 +1,22 @@
#ifndef NULLSOFT_BFC_PRECOMP_H
#define NULLSOFT_BFC_PRECOMP_H
// Platform
#include <bfc/platform/platform.h>
// Std
#include "wasabi_std.h"
#include "std_mem.h"
#include "wasabi_std_wnd.h"
#include "std_math.h"
#include "std_string.h"
// Containers
#include "memblock.h"
#include "tlist.h"
#include "stack.h"
#include "ptrlist.h"
#include "file/splitpath.h"
#endif

330
Src/Wasabi/bfc/ptrlist.cpp Normal file
View File

@ -0,0 +1,330 @@
#include "ptrlist.h"
#include <bfc/bfc_assert.h>
// if this symbol is enabled, do sanity checking in a bunch of methods
//#define DO_VERIFY_PTRLIST
#if defined(ASSERTS_ENABLED) && defined(DO_VERIFY_PTRLIST)
#define VERIFY_PTRLIST verify()
#else
#define VERIFY_PTRLIST
#endif
#ifdef _DEBUG
int ptrlist_totalnitems = 0;
#endif
PtrListRoot::PtrListRoot( int initial_size )
{
nitems = nslots = 0;
items = NULL;
//FG>why? we might as well save initial_size*4 bytes if nobody inserts anything in the list, no?
//BU No. initial_size defaults to 0 and therefore no memory is actually
//allocated in a typical construction. But, sometimes you want to start with
//a specific size, generally when you know the exact size you want,
//so that you can avoid REALLOCs when you initially populate the list.
//FG>Ah, makes sense.
setMinimumSize( initial_size );
}
PtrListRoot::PtrListRoot( const PtrListRoot *from )
{
nitems = nslots = 0;
items = NULL;
copyFrom( from );
}
PtrListRoot::~PtrListRoot()
{
removeAll();
}
void PtrListRoot::copyFrom( const PtrListRoot *from )
{
ASSERT( from != NULL );
removeAll();
appendFrom( from );
VERIFY_PTRLIST;
}
void PtrListRoot::appendFrom( const PtrListRoot *from )
{
ASSERT( from != NULL );
int n = from->getNumItems();
if ( n <= 0 )
return;
void **mem = from->getItemList();
ASSERT( mem != NULL ); // can't be NULL if getNumItems() >= 1
setMinimumSize( getNumItems() + n );
MEMCPY( items + getNumItems(), from->getItemList(), sizeof( void * ) * n );
nitems += n;
#ifdef _DEBUG
ptrlist_totalnitems += n;
#endif
VERIFY_PTRLIST;
}
void PtrListRoot::setMinimumSize( int _nslots )
{
ASSERT( _nslots >= 0 );
#ifdef DECREASE_PTRLISTS_SIZE
if ( _nslots + 2 * DEF_PTRLIST_INCREMENT < nslots )
{
nslots = ( ( _nslots / DEF_PTRLIST_INCREMENT ) + 2 ) * DEF_PTRLIST_INCREMENT;
items = (void **) REALLOC( items, sizeof( void * ) * nslots );
}
#endif
if ( _nslots == 0 || _nslots <= nslots )
return;
nslots = _nslots;
if ( items )
items = (void **) REALLOC( items, sizeof( void * ) * nslots );
else
items = (void **) MALLOC( sizeof( void * ) * nslots );
VERIFY_PTRLIST;
}
int PtrListRoot::getNumItems() const
{
return nitems;
}
void *PtrListRoot::enumItem( int n ) const
{
if ( items == NULL || n < 0 || n >= nitems )
return NULL;
return items[ n ];
}
void *PtrListRoot::addItem( void *item, int pos, int increment )
{
ASSERT( increment > 0 );
ASSERTPR( item != NULL, "can't put NULLs into ptrlists" );
ASSERT( nitems <= nslots );
#ifdef DECREASE_PTRLISTS_SIZE
// expand or shrink as necessary
if ( items == NULL || nslots == nitems )
setMinimumSize( nslots + increment );
else
setMinimumSize( nitems );
#else
// expand if necessary
if ( items == NULL || nslots == nitems )
setMinimumSize( nslots + increment );
#endif
items[ nitems++ ] = item;
if ( pos != PTRLIST_POS_LAST )
moveItem( nitems - 1, pos );
VERIFY_PTRLIST;
#ifdef _DEBUG
ptrlist_totalnitems++;
#endif
return item;
}
// replace what's in the slot with the new value
void *PtrListRoot::setItem( void *item, int pos )
{
ASSERT( nitems >= pos );
items[ pos ] = item;
VERIFY_PTRLIST;
return item;
}
void PtrListRoot::reverse()
{
if ( nitems <= 1 )
return;
MemBlock<void *> block( nitems, items );
void **blockmem = block.getMemory();
for ( int i = 0, j = nitems - 1; j >= 0; i++, j-- )
{
items[ i ] = blockmem[ j ];
}
}
void PtrListRoot::moveItem( int from, int to )
{
if ( from == to )
return;
void *ptr = items[ from ];
if ( nitems > from + 1 ) // if moving from the end, there is nothing to shift behind our src position
{
//IMPORTANT note for future ports: This assumes MEMCPY accepts overlapping segments.
MEMCPY( &items[ from ], &items[ from + 1 ], ( nitems - from ) * sizeof( void * ) );
}
if ( to > from )
to--;
if ( nitems > to ) // if moving to the end, there is nothing to shift behind our target position
MEMCPY( &items[ to + 1 ], &items[ to ], ( nitems - to - 1 ) * sizeof( void * ) );
items[ to ] = ptr;
VERIFY_PTRLIST;
}
int PtrListRoot::removeItem( void *item )
{
int c = 0;
if ( item == NULL || items == NULL || nitems <= 0 )
return 0;
// count occurences of item in items, remember the first one
void **p = items;
int first = -1;
for ( int i = 0; i < nitems; i++, p++ )
{
if ( *p == item )
{
if ( c++ == 0 )
first = i;
}
}
// if we found one, remove it
if ( c > 0 )
{
removeByPos( first ); // delByPos is faaast
c--; // decrease count
}
VERIFY_PTRLIST;
return c; // returns how many occurences of this item left
}
void PtrListRoot::removeEveryItem( void *item )
{
while ( removeItem( item ) );
VERIFY_PTRLIST;
}
void PtrListRoot::removeByPos( int pos )
{
if ( pos < 0 || pos >= nitems )
return; //JC
--nitems;
#ifdef _DEBUG
ptrlist_totalnitems--;
#endif
if ( pos == nitems )
return; // last one? nothing to copy over
MEMCPY( items + pos, items + ( pos + 1 ), sizeof( void * ) * ( nitems - pos ) ); // CT:not (nitems-(pos+1)) as nitems has been decremented earlier
#ifdef DECREASE_PTRLISTS_SIZE
// shrink if necessary
setMinimumSize( nitems );
#endif
VERIFY_PTRLIST;
}
void PtrListRoot::removeLastItem()
{
if ( nitems == 0 || items == NULL ) return;
nitems--; // hee hee
#ifdef _DEBUG
ptrlist_totalnitems--;
#endif
#ifdef DECREASE_PTRLISTS_SIZE
// shrink if necessary
setMinimumSize( nitems );
#endif
VERIFY_PTRLIST;
}
void PtrListRoot::removeAll()
{
FREE( items ); items = NULL;
#ifdef _DEBUG
ptrlist_totalnitems -= nitems;
#endif
#ifdef DECREASE_PTRLISTS_SIZE
// shrink if necessary
setMinimumSize( nitems );
#endif
nitems = 0;
nslots = 0;
VERIFY_PTRLIST;
}
void PtrListRoot::freeAll()
{
for ( int i = 0; i < nitems; i++ ) //JC
if ( items ) FREE( items[ i ] );
removeAll();
VERIFY_PTRLIST;
}
int PtrListRoot::searchItem( void *item ) const
{
for ( int i = 0; i < nitems; i++ )
if ( items[ i ] == item )
return i;
return -1;
}
void PtrListRoot::verify()
{
#ifdef DO_VERIFY_PTRLIST
ASSERT( nitems >= 0 );
ASSERT( nslots >= 0 );
ASSERT( nitems <= nslots );
#endif
}
#if 0
int PtrListRoot::bsearchItem( void *item ) const
{
// do binary search
if ( nitems == 0 || items == NULL ) return -1;
int bot = 0, top = nitems - 1, mid;
for ( int c = 0; c < nitems + 16; c++ )
{
if ( bot > top ) return -1;
mid = ( bot + top ) / 2;
if ( item == items[ mid ] ) return mid;
if ( item < items[ mid ] ) top = mid - 1;
else bot = mid + 1;
}
ASSERTPR( 0, "binary search fucked up" );
return -1;
}
#endif
void PtrListRoot::purge()
{
ASSERT( nitems == 0 );
if ( items != NULL )
{
FREE( items );
items = NULL;
}
}

777
Src/Wasabi/bfc/ptrlist.h Normal file
View File

@ -0,0 +1,777 @@
#ifndef _PTRLIST_H
#define _PTRLIST_H
#include <bfc/std_math.h>
//#include <bfc/memblock.h>
#include <bfc/bfc_assert.h>
#include <bfc/platform/platform.h>
//#include <wasabicfg.h>
#ifdef _DEBUG
extern int ptrlist_totalnitems;
#endif
// Disable the "identifier was truncated to '255' characters..." warning.
#pragma warning( disable : 4786 )
/*
a generic pointer list template. only takes up 12 bytes when empty. auto-grows
the array as necessary, NEVER shrinks it unless you removeAll() or equivalent
Use, PtrList<typename>, never PtrListRoot
*/
// yes, this really should be an enum or something
#define PTRLIST_POS_LAST -1
// 4k each, leaving 16 bytes for MALLOC overhead
//#define DEF_PTRLIST_INCREMENT (4096/sizeof(void*)-16)
// in average, 4k doubles the VM working set of a skin, 128bytes (32 elements) seems most optimal
#define DEF_PTRLIST_INCREMENT (128)
class __foreach;
// base class, to share as much code as possible
class NOVTABLE PtrListRoot
{
friend class __foreach;
protected:
PtrListRoot(int initial_size = 0);
PtrListRoot(const PtrListRoot *from);
virtual ~PtrListRoot();
void copyFrom(const PtrListRoot *from);
void appendFrom(const PtrListRoot *from);
void setMinimumSize(int nslots); // expand to at least this many slots
int getNumItems() const;
int size() const { return nitems; }
bool empty() { return nitems == 0; }
void *enumItem(int n) const;
void moveItem(int from, int to);
int removeItem(void *item);
void removeEveryItem(void *item);
void removeByPos(int pos);
void removeLastItem();
void removeAll();
void freeAll();
void purge();
// gross-ass linear search to find index of item
// note that PtrListSorted provides a binary search version
int searchItem(void *item) const;
#if 0//fuct
// speedy binary search. although it'll be fuct if it's not sorted right
int bsearchItem(void *item) const;
#endif
void *addItem(void *item, int pos, int inc);
void *setItem(void *item, int pos); // replace what's in the slot with the new value
void reverse();
void **getItemList() const { return items; } // try to avoid! this is inline to make q() fast
private:
#undef verify // for Mac
void verify();
int nitems, nslots;
void **items;
};
// now we add the methods that refer specifically to the pointer type
template <class T>
class PtrList : public PtrListRoot
{
friend class __foreach;
public:
PtrList(int initial_size = 0) {}
PtrList(const PtrList<T> &r) { copyFrom(&r); }
PtrList(const PtrList<T> *r) { copyFrom(r); }
~PtrList() {}
// copy another PtrList
// deletes previous contents
void copyFrom(const PtrList<T> *from) { PtrListRoot::copyFrom(from); }
// append contents of another PtrList to the end of this one
// preserves previous contents
void appendFrom(const PtrList<T> *from) { PtrListRoot::appendFrom(from); }
// adding
// expand freelist to at least this many slots, even if 0 items in list
void setMinimumSize(int nslots) { PtrListRoot::setMinimumSize(nslots); }
// provide a public addItem for the pointer type
T *addItem(const T *item, int pos = PTRLIST_POS_LAST, int inc = DEF_PTRLIST_INCREMENT)
{
return static_cast<T *>(PtrListRoot::addItem(const_cast<T*>(item), pos, inc));
}
void push_back(const T* item) { return addItem(item); }
// replace what's in the slot with the new value
T *setItem(const T *item, int pos) { return static_cast<T *>(PtrListRoot::setItem(const_cast<T*>(item), pos)); }
// reverse the order of the list in place
void reverse() { PtrListRoot::reverse(); }
// enumerating
// returns # of items in list
int getNumItems() const { return PtrListRoot::getNumItems(); }
// basic list enumerator. returns NULL for out of bounds
T *enumItem(int n) const { return static_cast<T *>(PtrListRoot::enumItem(n)); }
T *operator[](int n) const { return enumItem(n); }
// this will safely return NULL if 0 items due to enumItems's boundscheck
T *getFirst() const { return enumItem(0); }
T *getLast() const { return enumItem(getNumItems() - 1); }
// this is a NON-BOUNDS-CHECKING lookup
T *q(int n) { return static_cast<T*>(getItemList()[n]); }
// gross-ass linear search to find index of item
// note that PtrListSorted provides a binary search version
int searchItem(T *item) const { return PtrListRoot::searchItem(item); }
int haveItem(T *item) const { return searchItem(item) >= 0; }
// deleteing
// removes first instance of a pointer in list, returns how many are left
int removeItem(T *item) { return PtrListRoot::removeItem(item); }
//DEPRECATED
int delItem(T *item) { return removeItem(item); }
// removes all instances of this pointer
void removeEveryItem(const T *item) { PtrListRoot::removeEveryItem(const_cast<T*>(item)); }
// removes pointer at specified position regardless of value
void removeByPos(int pos) { PtrListRoot::removeByPos(pos); }
// DEPRECATED
void delByPos(int pos) { removeByPos(pos); }
// removes last item
void removeLastItem() { PtrListRoot::removeLastItem(); }
// removes all entries, also deletes memory space
void removeAll() { PtrListRoot::removeAll(); }
// removes all entries, calling FREE on the pointers
void freeAll() { PtrListRoot::freeAll(); }
// removes all entries, calling delete on the pointers
void deleteAll()
{
int i, nitems = getNumItems();
for (i = 0; i < nitems; i++)
delete enumItem(i);
removeAll();
}
// removes all entries, calling delete on the pointers
// FG>this version removes each entry as it deletes it so if
// one of the object uses this list in its destructor, it will
// still work. It is MUCH slower than deleteAll tho.
void deleteAllSafe()
{
//CUT ASSERT(!(nitems != 0 && items == NULL));
while (getNumItems())
{
T *i = enumItem(0);
delete i;
removeItem(i);
}
}
void deleteItem(int item)
{
if (item < getNumItems())
{
deleteItem(enumItem(item));
}
}
void deleteItem(T *item)
{
delete item;
removeItem(item);
}
void moveItem(int from, int to) { PtrListRoot::moveItem(from, to); }
static T *castFor(void *ptr) { return static_cast<T*>(ptr); }
using PtrListRoot::purge;
protected:
T **getItemList()
{
return reinterpret_cast<T **>(PtrListRoot::getItemList());
}
};
class NotSorted
{
public:
// comparator for searching -- override
static int compareAttrib(const wchar_t *attrib, void *item) { return 0; }
// comparator for sorting -- override , -1 p1 < p2, 0 eq, 1 p1 > p2
static int compareItem(void *p1, void* p2) { return CMP3(p1, p2); }
};
//template <class T, class C> class NoSort {
// static void _sort(T **, int) {}
//};
// a base class to sort the pointers
// you must implement the comparisons (C) and the sort algorithm (S)
template < class T, class C, class S >
class PtrListSorted : public PtrList<T>
{
public:
PtrListSorted(int initial_size = 0) : PtrList<T>(initial_size)
{
need_sorting = 0;
auto_sort = true;
dups_low = dups_hi = dups_pos = 0;
}
void copyFrom(const PtrList<T> *from)
{
PtrList<T>::copyFrom(from);
need_sorting = 1;
if (auto_sort) sort();
}
T *addItem(T *item, int pos = PTRLIST_POS_LAST, int inc = DEF_PTRLIST_INCREMENT)
{
#if 1
// check for appending in sorted order
if (pos == PTRLIST_POS_LAST && !need_sorting && auto_sort)
{
int n = PtrList<T>::getNumItems();
if (n > 0 && C::compareItem(item, q(n - 1)) < 0) need_sorting = 1;
}
else
#endif
need_sorting = 1;
return PtrList<T>::addItem(item, pos, inc);
}
void sort(bool force_sort = false)
{
if (need_sorting || force_sort)
S::_sort(PtrList<T>::getItemList(), PtrList<T>::getNumItems());
need_sorting = 0;
}
T *enumItem(int n)
{ // NOT const since we might call sort()
if (auto_sort) sort();
return PtrList<T>::enumItem(n);
}
T *operator[](int n) { return PtrListSorted<T, C, S>::enumItem(n); }
T *q(int n)
{
if (auto_sort) sort();
return static_cast<T*>(PtrList<T>::getItemList()[n]);
}
T *findItem(const wchar_t *attrib, int *pos = NULL)
{
ASSERTPR(!(!auto_sort && need_sorting), "must call sort() first if auto-sorting is disabled");
sort();
#if 1 // do binary search
if (PtrList<T>::getNumItems() == 0) return NULL;
int bot = 0, top = PtrList<T>::getNumItems() - 1, mid;
for (int c = 0; c < PtrList<T>::getNumItems() + 1; c++)
{
if (bot > top) return NULL;
mid = (bot + top) / 2;
int r = C::compareAttrib(attrib, PtrList<T>::getItemList()[mid]);
if (r == 0)
{
if (pos != NULL) *pos = mid;
return PtrList<T>::getItemList()[mid];
}
if (r < 0)
{
top = mid - 1;
}
else
{
bot = mid + 1;
}
}
ASSERTPR(0, "binary search fucked up");
#else
// re-enable this in case of fuckup
for (int i = 0; i < nitems; i++)
{
if (C::compareAttrib(attrib, static_cast<T *>(items[i])) == 0)
return static_cast<T *>items[i];
}
#endif
return NULL;
}
T *findItem(T *attrib, int *pos = NULL)
{
return findItem((const wchar_t *)attrib, pos);
}
int beginEnumDups(const char *attrib)
{
int pos;
findItem(attrib, &pos);
if (pos < 0)
return -1;
dups_hi = pos;
dups_low = pos;
int i;
for (i = pos - 1;i >= 0;i--)
{
if (C::compareAttrib(attrib, static_cast<T *>(enumItem(i))) == 0)
break;
dups_low = i;
}
for (i = pos + 1;i < PtrList<T>::getNumItems();i++)
{
if (C::compareAttrib(attrib, static_cast<T *>(enumItem(i))) == 0)
break;
dups_hi = i;
}
dups_pos = dups_low;
return dups_pos;
}
int getNextDup()
{ // returns -1 when done
if (dups_pos >= dups_hi)
return -1;
return ++dups_pos;
}
#if 0
// replace search with binary search
int searchItem(T *item) const
{
ASSERTPR(!(!auto_sort && need_sorting), "must call sort() first if auto-sorting is disabled");
sort();
return bsearchItem(item);
}
#endif
void setAutoSort(bool as) { auto_sort = as; }
bool getAutoSort() const { return auto_sort; }
void removeDups()
{
ASSERTPR(!(!auto_sort && need_sorting), "must call sort() first if auto-sorting is disabled");
sort();
for (int i = 1; i < PtrList<T>::getNumItems(); i++)
{
if (C::compareItem(enumItem(i - 1), enumItem(i)) == 0)
{
PtrList<T>::delByPos(i);
i--;
}
}
}
private:
int need_sorting;
bool auto_sort;
int dups_low, dups_hi, dups_pos;
};
// quicksort -- you still need to override the compare fns
template <class T, class C>
class QuickSorted
{
public:
static void _sort(T **items, int nitems)
{
if (items == NULL || nitems <= 1)
return ;
Qsort(items, 0, nitems - 1);
}
private:
static void swapItem(T **items, int a, int b)
{ // no bounds checking!
T *tmp = items[a];
items[a] = items[b];
items[b] = tmp;
}
static void Qsort(T **items, int lo0, int hi0)
{
int lo = lo0, hi = hi0;
if (hi0 > lo0)
{
T *mid = items[(lo0 + hi0) / 2];
while (lo <= hi)
{
while ((lo < hi0) && (C::compareItem(items[lo], mid) < 0))
lo++;
while ((hi > lo0) && (C::compareItem(items[hi], mid) > 0))
hi--;
if (lo <= hi)
{
swapItem(items, lo, hi);
lo++;
hi--;
}
}
if (lo0 < hi)
Qsort(items, lo0, hi);
if (lo < hi0)
Qsort(items, lo, hi0);
}
}
};
// easy way to specify quicksorting, just data type and comparison class
template <class T, class C> class PtrListQuickSorted : public PtrListSorted<T, C, QuickSorted<T, C> >
{
public:
PtrListQuickSorted(int initial_size = 0) : PtrListSorted<T, C, QuickSorted<T, C> >(initial_size) {}
};
// easy way to get a list sorted by pointer val
class SortByPtrVal
{
public:
static int compareItem(void *p1, void *p2) { return CMP3(p1, p2); }
static int compareAttrib(const wchar_t *attrib, void *item) { return CMP3((void *)attrib, item); }
};
template <class T> class PtrListQuickSortedByPtrVal : public PtrListQuickSorted<T, SortByPtrVal > {};
// this class automatically inserts at the correct position, so
// the binary searches are very fast if you need to insert and search often (no need to sort)
template < class T, class C >
class PtrListInsertSorted : public PtrList<T>
{
public:
PtrListInsertSorted() : last_insert_pos(0) { disable_sort = 0; }
T *addItem(T *item)
{
int numItems = PtrList<T>::getNumItems();
if (numItems == 0)
{
last_insert_pos = 0;
return PtrList<T>::addItem(item);
}
int insertpoint = -1;
if (!disable_sort)
{
int bot = 0, top = numItems - 1, mid;
// benski>
// optimization based on profiler info. Too many string compares!
// Most of the use of this comes from GuiObjectWnd's constructor (and derived classes)
// so I've changed GuiObjectWnd to add things in alphabetical order.
// Before we start the binary search, we'll check the new item against the LAST item inserted
// Most of the time, we'll finish the insert in O(1)
// Even if we fail, we mitigate the loss somewhat by limiting the binary search
if (last_insert_pos >= numItems) // the list may have shrunk since last time
last_insert_pos = numItems - 1;
int quickTest = C::compareItem(item, PtrList<T>::getItemList()[last_insert_pos]);
if (quickTest == 0) // right on the money.. we'll go ahead and insert ourselves next
return PtrList<T>::addItem(item, last_insert_pos);
if (quickTest > 0) // ok we go after the last inserted item (good), but we need to make sure we go before the next one
{
last_insert_pos++;
if (last_insert_pos == numItems) // we're at the end? cool...
return PtrList<T>::addItem(item, PTRLIST_POS_LAST);
quickTest = C::compareItem(item, PtrList<T>::getItemList()[last_insert_pos]); // test against the next item
if (quickTest <= 0) // and we're not bigger than the next one... perfect!
return PtrList<T>::addItem(item, last_insert_pos);
else // too bad
bot = last_insert_pos; // help out the binary search ... We're at least bigger than everything before last_insert_pos
}
else // ok our optimization failed, but we can still help out the binary search
top = last_insert_pos - 1; // we're at least smaller than everything before last_insert_pos
// end optimization code
for (int c = 0; c < numItems + 1; c++)
{
if (bot > top)
{
// insert here
insertpoint = bot;
break;
}
mid = (bot + top) / 2;
int r = C::compareItem(item, PtrList<T>::getItemList()[mid]);
if (r == 0)
{
// insert here
insertpoint = mid;
break;
}
if (r < 0)
{
top = mid - 1;
}
else
{
bot = mid + 1;
}
}
last_insert_pos = insertpoint;
ASSERTPR(insertpoint != -1, "insertsort/binary search fucked up");
}
else // no sorting
{
last_insert_pos = numItems;
insertpoint = PTRLIST_POS_LAST;
}
return PtrList<T>::addItem(item, insertpoint);
}
T *getInsertionPoint(T *item, int *pos)
{
if (PtrList<T>::getNumItems() == 0)
{
if (pos)
*pos = 0;
return NULL;
}
int bot = 0, top = PtrList<T>::getNumItems() - 1, mid;
int insertpoint = -1;
if (!disable_sort )
{
for (int c = 0; c < PtrList<T>::getNumItems() + 1; c++)
{
if (bot > top)
{
// insert here
insertpoint = bot;
break;
}
mid = (bot + top) / 2;
int r = C::compareItem(item, PtrList<T>::getItemList()[mid]);
if (r == 0)
{
// insert here
insertpoint = mid;
break;
}
if (r < 0)
{
top = mid - 1;
}
else
{
bot = mid + 1;
}
}
ASSERTPR(insertpoint != -1, "insertsort/binary search fucked up");
}
else
insertpoint = PTRLIST_POS_LAST;
if (pos)
*pos = insertpoint;
return PtrList<T>::enumItem(insertpoint);
}
T *findItem(const wchar_t *attrib, int *pos = NULL)
{
if (isSorted())
{
// binary search
if (PtrList<T>::getNumItems() == 0)
return NULL;
int bot = 0, top = PtrList<T>::getNumItems() - 1, mid;
for (int c = 0; c < PtrList<T>::getNumItems() + 1; c++)
{
if (bot > top)
return NULL;
mid = (bot + top) / 2;
int r = C::compareAttrib(attrib, PtrList<T>::getItemList()[mid]);
if (r == 0)
{
if (pos != NULL)
*pos = mid;
return PtrList<T>::getItemList()[mid];
}
if (r < 0)
{
top = mid - 1;
}
else
{
bot = mid + 1;
}
}
ASSERTPR(0, "binary search fucked up");
}
else
{
// linear search
for (int i = 0; i < PtrList<T>::getNumItems(); i++)
{
int r = C::compareAttrib(attrib, PtrList<T>::getItemList()[i]);
if (r == 0)
{
if (pos != NULL)
*pos = i;
return PtrList<T>::getItemList()[i];
}
}
}
return NULL;
}
T *findItem(T *attrib, int *pos = NULL) { return findItem((const wchar_t *)attrib, pos); }
void setSorted(int dosort) { disable_sort = !dosort; }
int isSorted() { return !disable_sort; }
int disable_sort;
int last_insert_pos;
};
// this list allows you to have multiple items with same attrib and adds findLastItem so you can
// sort on more than just one item. this can be used to make autosorting lists of overriding items
// which you can add and remove at will.
template <class T, class C> class PtrListQuickMultiSorted : public PtrListQuickSorted<T, C>
{
public:
PtrListQuickMultiSorted(int initial_size = 0) : PtrListQuickSorted<T, C>(initial_size) {}
T *findLastItem(const wchar_t *attrib, int *pos = NULL)
{
PtrListQuickSorted<T, C>::sort();
int p = 0;
int fp = 0;
T *item = PtrListQuickSorted<T, C>::findItem(attrib, &fp);
if (!item)
return NULL;
p = fp;
for(;;)
{
p++;
if (p >= PtrListQuickSorted<T, C>::getNumItems())
break;
T* i = PtrListQuickSorted<T, C>::enumItem(p);
if (!C::compareAttrib(attrib, i))
{
fp = p;
item = i;
}
else
break;
}
if (pos != NULL)
*pos = fp;
return item;
}
};
//same thing but Insert sorted. use this one if you insert and search items often (no need to sort on findItem)
template <class T, class C> class PtrListInsertMultiSorted : public PtrListInsertSorted<T, C>
{
public:
PtrListInsertMultiSorted() : PtrListInsertSorted<T, C>() {}
T *findLastItem(const wchar_t *attrib, int *pos = NULL)
{
//sort();
int p = 0;
int fp = 0;
T *item = PtrListInsertSorted<T, C>::findItem(attrib, &fp);
if (!item)
return NULL;
p = fp;
for (;;)
{
p++;
if (p >= PtrListInsertSorted<T, C>::getNumItems())
break;
T* i = PtrListInsertSorted<T, C>::enumItem(p);
if (!C::compareAttrib(attrib, i))
{
fp = p;
item = i;
}
else
break;
}
if (pos != NULL)
*pos = fp;
return item;
}
};
#include <bfc/foreach.h>
#endif

View File

@ -0,0 +1,78 @@
#ifndef __REENTRYFILTER_H
#define __REENTRYFILTER_H
#include <bfc/tlist.h>
class ReentryFilterObject {
public:
ReentryFilterObject() {}
virtual ~ReentryFilterObject() {}
void enterScope(int scope) {
scopes.addItem(scope);
}
int isInScope(int scope) {
for (int i=0;i<scopes.getNumItems();i++)
if (scopes.enumItem(i) == scope) return 1;
return 0;
}
void leaveScope(int scope) {
for (int i=0;i<scopes.getNumItems();i++)
if (scopes.enumItem(i) == scope) {
scopes.delByPos(i);
return;
}
}
private:
TList<int> scopes;
};
class ReentryFilter {
public:
ReentryFilter() : reentering(0), thisscope(-1), filter(NULL) {} // call setFilterObject, enterScope and leaveScope manually
ReentryFilter(ReentryFilterObject *filterobj, intptr_t scope) {
setFilterObject(filterobj);
enterScope(scope);
}
void setFilterObject(ReentryFilterObject *filterobj) {
filter = filterobj;
}
void enterScope(intptr_t scope) {
ASSERT(filter != NULL);
if (filter->isInScope(scope)) {
reentering = 1;
} else {
filter->enterScope(scope);
reentering = 0;
}
thisscope = scope;
}
void leaveScope() {
ASSERT(filter != NULL);
filter->leaveScope(thisscope);
}
virtual ~ReentryFilter() {
if (reentering) return;
leaveScope();
}
int mustLeave() { return reentering; }
private:
intptr_t thisscope;
int reentering;
ReentryFilterObject *filter;
};
#endif

77
Src/Wasabi/bfc/stack.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "precomp_wasabi_bfc.h"
#include "stack.h"
//#define STACK_SIZE_INCREMENT 250
// going from 250 to 32 decreases size of VM working set by several megabytes
#define STACK_SIZE_INCREMENT 32
StackBase::StackBase()
{
nslots = 0;
cur = 0;
stack = NULL;
}
StackBase::~StackBase()
{
if (stack != NULL) FREE(stack);
}
int StackBase::push(void *item, int sizeofT, int increment)
{
if (increment <= 0) increment = STACK_SIZE_INCREMENT;
if (stack == NULL) {
nslots = increment;
stack = (char*)MALLOC(sizeofT * nslots);
} else if (cur >= nslots) {
int newnslots = nslots + increment;
stack = (char*)REALLOC(stack, sizeofT*newnslots);
nslots = newnslots;
}
MEMCPY(stack + cur*sizeofT, item, sizeofT);
cur++;
return cur;
}
int StackBase::peek() {
return cur;
}
int StackBase::peekAt(void *ptr, int n, int sizeofT) {
if (ptr != NULL) MEMCPY(ptr, stack + (cur-1-n)*sizeofT, sizeofT);
return cur;
}
int StackBase::getRef(void **ptr, int n, int sizeofT) {
if (ptr != NULL) *ptr = stack + (cur-1-n)*sizeofT;
return cur;
}
void *StackBase::top(int sizeofT) {
ASSERT(cur >= 0);
if (cur == 0) return NULL;
return stack + (cur-1)*sizeofT;
}
int StackBase::pop(void *ptr, int sizeofT) {
ASSERT(cur >= 0);
if (cur == 0) return 0;
ASSERT(stack != NULL);
--cur;
if (ptr != NULL) MEMCPY(ptr, stack + cur*sizeofT, sizeofT);
return 1;
}
int StackBase::isempty() {
return cur == 0;
}
void StackBase::purge() {
ASSERT(isempty());
if (stack != NULL) {
FREE(stack);
stack = NULL;
}
}

42
Src/Wasabi/bfc/stack.h Normal file
View File

@ -0,0 +1,42 @@
//PORTABLE
#ifndef _STACK_H
#define _STACK_H
#include <bfc/common.h>
#include <bfc/wasabi_std.h>
// a self-growing stack. note that it never shrinks (for now)
class StackBase {
protected:
StackBase();
~StackBase();
int push(void *item, int sizeofT, int increment);
int peek();
int peekAt(void *ptr, int n, int sizeofT);
int getRef(void **ptr, int n, int sizeofT);
void *top(int sizeofT);
int pop(void *ptr, int sizeofT);
int isempty();
void purge();
private:
int nslots, cur;
char *stack;
};
template<class T>
class Stack : public StackBase {
public:
int push(T item, int increment=-1) { return StackBase::push(&item, sizeof(T), increment); }
using StackBase::peek;
T top() { return *static_cast<T*>(StackBase::top(sizeof(T))); }
int peekAt(T *ptr = NULL, int n = 0) { return StackBase::peekAt(ptr, n, sizeof(T)); }
int getRef(T **ptr = NULL, int n = 0) { if (!ptr) return peek(); return StackBase::getRef((void **)&(*ptr), n, sizeof(T)); }
int pop(T *ptr = NULL) { return StackBase::pop(ptr, sizeof(T)); }
using StackBase::isempty;
using StackBase::purge;
};
#endif

428
Src/Wasabi/bfc/std_file.cpp Normal file
View File

@ -0,0 +1,428 @@
#include "precomp_wasabi_bfc.h"
#include "std_file.h"
#include <bfc/file/readdir.h>
#include <bfc/platform/strcmp.h>
#ifdef WIN32
#include <shellapi.h> // for ShellExecute
#endif
#ifdef __APPLE__
#include <unistd.h>
#endif
#define TMPNAME_PREFIX L"WTF"
#ifndef _NOSTUDIO
#include <bfc/parse/pathparse.h>
#undef fopen
#undef fclose
#undef fseek
#undef ftell
#undef fread
#undef fwrite
#undef fgets
#undef fprintf
#undef unlink
#undef access
#ifdef WASABI_COMPILE_FILEREADER
static PtrList<void> fileReaders;
OSFILETYPE FileReaderOpen(const wchar_t *filename, OSFNCSTR mode)
{
OSFILETYPE ret = NULL;
const wchar_t *rFilename = filename;
wchar_t str[WA_MAX_PATH] = L"";
if (wcsstr(filename, L".."))
{
PathParserW pp(filename);
for (int i = 0;i < pp.getNumStrings();i++)
{
if (!wcscmp(pp.enumString(i), L".."))
{
PathParserW pp2(str);
if (pp2.getNumStrings() <= 0)
return NULL;
ASSERTPR(pp2.getNumStrings() > 0, "we don't handle this right, and I'm not sure how to fix it because I'm not sure what the code should do with a leading .. --BU");
int l = (int)wcslen(pp2.enumString(pp2.getNumStrings() - 1));
str[wcslen(str) - l - 1] = 0;
continue;
}
if (!wcscmp(pp.enumString(i), L"."))
continue;
wcscat(str, pp.enumString(i));
wcscat(str, L"/");
}
str[wcslen(str) - 1] = 0;
rFilename = str;
}
if (WASABI_API_FILE && (ret = (OSFILETYPE )WASABI_API_FILE->fileOpen(rFilename, mode)))
{
fileReaders.addItem((void *)ret);
return ret;
}
return 0;
}
#endif
static DWORD mode_to_access(const wchar_t *mode)
{
DWORD access_flags=0;
if (mode)
{
if (mode[0]=='r')
access_flags|=GENERIC_READ;
if (mode[0]=='w' || mode[0] == 'a')
{
access_flags|=GENERIC_WRITE;
if (mode[1] == '+')
access_flags|=GENERIC_READ;
}
}
return access_flags;
}
static DWORD mode_to_create(const wchar_t *mode)
{
if (mode[0]=='r')
return OPEN_EXISTING;
if (mode[0] == 'w')
return CREATE_ALWAYS;
if (mode[0] == 'a')
return OPEN_ALWAYS;
return OPEN_ALWAYS;
}
OSFILETYPE WFOPEN(const wchar_t *filename, OSFNCSTR mode, bool useFileReaders)
{
if (!filename || !*filename)
return OPEN_FAILED;
if (!mode)
mode = WF_WRITE_BINARY;
OSFILETYPE ret = OPEN_FAILED;
if (!WCSNICMP(filename, L"file:", 5))
filename += 5;
#ifdef _WIN32
ret = CreateFileW(filename, mode_to_access(mode), FILE_SHARE_READ, 0, mode_to_create(mode), FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (ret != OPEN_FAILED && mode[0]=='a')
SetFilePointer(ret, 0, 0, FILE_END);
#elif defined(__APPLE__)
// this is kind of slow, but hopefully this function isn't called enough for a major performance impact
// maybe it'd be faster if we did -fshort-wchar and used CFStringCreateWithCharactersNoCopy
CFStringRef cfstr = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)filename, wcslen(filename)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
if (cfstr)
{
size_t len = CFStringGetMaximumSizeOfFileSystemRepresentation(cfstr);
if (len)
{
char *tmpfn = alloca(len);
if (tmpfn)
{
if (CFStringGetFileSystemRepresentation(cfstr, tmpfn, len))
ret = fopen(tmpfn, mode);
}
}
CFRelease(cfstr);
}
#else
#error port me
#endif
if (ret != OPEN_FAILED)
return ret;
// File not found... try to open it with the file readers
// but before that, resolve ".." in path so zip can find it
#ifdef WASABI_COMPILE_FILEREADER
if (useFileReaders)
{
if (ret = FileReaderOpen(filename, mode))
return ret;
else
return OPEN_FAILED;
}
#endif
// File still not found ...
return OPEN_FAILED;
}
int FCLOSE(OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
{
fileReaders.removeItem((void *)stream);
WASABI_API_FILE->fileClose((void *)stream);
return 0;
}
#endif
return !CloseHandle(stream);
}
static __int64 Seek64(HANDLE hf, __int64 distance, DWORD MoveMethod)
{
LARGE_INTEGER li;
li.QuadPart = distance;
li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
{
li.QuadPart = -1;
}
return li.QuadPart;
}
int FSEEK(OSFILETYPE stream, long offset, int origin)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
return WASABI_API_FILE->fileSeek(offset, origin, (void *)stream);
#endif
return (int)Seek64(stream, offset, origin);
}
uint64_t FTELL(OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
return WASABI_API_FILE->fileTell((void *)stream);
#endif
return Seek64(stream, 0, FILE_CURRENT);
}
size_t FREAD(void *buffer, size_t size, size_t count, OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
return WASABI_API_FILE->fileRead(buffer, size*count, (void *)stream);
#endif
DWORD bytesRead=0;
ReadFile(stream, buffer, (DWORD)(size*count), &bytesRead, NULL);
return bytesRead;
}
size_t FWRITE(const void *buffer, size_t size, size_t count, OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
return WASABI_API_FILE->fileWrite(buffer, (int)(size*count), (void *)stream);
#endif
DWORD bytesWritten=0;
WriteFile(stream, buffer, (DWORD)(size*count), &bytesWritten, NULL);
return bytesWritten;
}
uint64_t FGETSIZE(OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
return WASABI_API_FILE->fileGetFileSize((void *)stream);
#endif
LARGE_INTEGER position;
position.QuadPart=0;
position.LowPart = GetFileSize(stream, (LPDWORD)&position.HighPart);
if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
return INVALID_FILE_SIZE;
else
return position.QuadPart;
}
/*
char *FGETS(char *string, int n, OSFILETYPE stream)
{
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
{
char c;
char *p = string;
for (int i = 0;i < (n - 1);i++)
{
if (!WASABI_API_FILE->fileRead(&c, 1, stream))
{
if (!i) return NULL;
break;
}
if (c == 0x0d) continue;
if (c == 0x0a) break;
*p++ = c;
}
*p = 0;
return string;
}
#endif
return fgets(string, n, stream);
}
*/
/*
int FPRINTF(OSFILETYPE stream, const char *format , ...)
{
int ret;
va_list args;
va_start (args, format);
#ifdef WASABI_COMPILE_FILEREADER
if (fileReaders.searchItem((void *)stream) != -1)
{
String p;
ret = p.vsprintf(format, args);
FWRITE(p.v(), p.len(), 1, stream);
}
else
#endif
ret = vfprintf(stream, format, args); //real stdio
va_end (args);
return ret;
}*/
OSFNCSTR TMPNAM2(OSFNSTR str, int val)
{
#ifdef WIN32
wchar_t tempPath[MAX_PATH-14] = {0};
static wchar_t tempName[MAX_PATH];
GetTempPathW(MAX_PATH-14, tempPath);
GetTempFileNameW(tempPath, TMPNAME_PREFIX, val, tempName);
if (str)
{
wcsncpy(str, tempName, MAX_PATH);
return str;
}
else
{
return tempName;
}
#elif defined(LINUX) || defined(__APPLE__)
mkstemp(StringPrintf("%sXXXXXX", str).getNonConstVal());
return (const char *)str;
#endif
}
OSFNCSTR TMPNAM(OSFNSTR string)
{
return TMPNAM2(string, 0);
}
int UNLINK(OSFNCSTR filename)
{
#ifdef WASABI_COMPILE_FILEREADER
return FDELETE(filename);
#elif defined(_WIN32)
return _wunlink(filename);
#else
return unlink(filename); // this has been undefed at the top of this file
#endif
}
int ACCESS(const char *filename, int mode)
{
#ifdef WIN32
return _access(filename, mode);
#else
return access(filename, mode); // this has been undefed at the top of this file
#endif
}
int WACCESS(OSFNCSTR filename, int mode)
{
#ifdef WIN32
return _waccess(filename, mode);
#elif defined(__APPLE__)
return access(filename, mode); // this has been undefed at the top of this file
#endif
}
int FDELETE(const wchar_t *filename, int permanently)
{
#ifdef WASABI_COMPILE_FILEREADER
if (permanently)
return WASABI_API_FILE->fileRemove(filename);
else
return WASABI_API_FILE->fileRemoveUndoable(filename);
#else
return UNLINK(filename);
#endif
}
int MOVEFILE(const wchar_t * filename, const wchar_t *destfilename)
{
#ifdef WASABI_COMPILE_FILEREADER
return WASABI_API_FILE->fileMove(filename, destfilename);
#elif defined(_WIN32)
return MoveFileW(filename, destfilename);
#else
return rename(filename, destfilename);
#endif
}
#ifdef WIN32
#include <shlobj.h>
#include <shellapi.h>
static HRESULT ResolveShortCut(LPCWSTR pszShortcutFile, LPWSTR pszPath, int maxbuf)
{
HRESULT hres;
IShellLinkW* psl;
wchar_t szGotPath[MAX_PATH] = {0};
WIN32_FIND_DATAW wfd;
*pszPath = 0; // assume failure
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLinkW, (void **) & psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (void **) & ppf); // OLE 2! Yay! --YO
if (SUCCEEDED(hres))
{
hres = ppf->Load(pszShortcutFile, STGM_READ);
if (SUCCEEDED(hres))
{
hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);
if (SUCCEEDED(hres))
{
wcsncpy(szGotPath, pszShortcutFile, MAX_PATH);
hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATAW *) & wfd,
SLGP_SHORTPATH );
wcsncpy(pszPath, szGotPath, maxbuf);
if (maxbuf) pszPath[maxbuf] = 0;
}
}
ppf->Release();
}
psl->Release();
}
return SUCCEEDED(hres);
}
#endif
// ommitting a maxbuf param was just asking for trouble...
int StdFile::resolveShortcut(OSFNCSTR filename, OSFNSTR destfilename, int maxbuf)
{
#ifdef WIN32
return ResolveShortCut(filename, destfilename, maxbuf);
#elif defined(LINUX) || defined(__APPLE__)
return readlink(filename, destfilename, maxbuf);
#else
#error port me
#endif
}
#endif // ndef _NOSTUDIO

101
Src/Wasabi/bfc/std_file.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef _STD_FILE_H
#define _STD_FILE_H
#include <bfc/platform/platform.h>
#include "wasabi_std.h"
#include <stdio.h>
/* TODO:
FEOF
FFLUSH
FGETPOS - maybe implement as just FTELL?
FSETPOS - maybe implement as just FSEEK?
FPUTS - no problems, look at FPRINTF implementation
FSTAT (in conjunction with FILENO), only fill in _stat::st_size for now (via getFileSize)
*/
#ifndef _NOSTUDIO
// EXTC is used here as some .c files will use these functions
#define NO_FILEREADERS false
#ifdef _WIN32
#define WF_READONLY_BINARY L"rb"
#define WF_WRITE_TEXT L"wt"
#define WF_WRITE_BINARY L"wb"
#define WF_APPEND L"a"
#define WF_APPEND_RW L"a+"
#define OPEN_FAILED INVALID_HANDLE_VALUE
#elif defined(__APPLE__)
#define WF_READONLY_BINARY "r"
#define WF_WRITE_TEXT "w"
#define WF_WRITE_BINARY "w"
#define WF_APPEND "a"
#define WF_APPEND_RW "a+"
#define OPEN_FAILED 0
#endif
#ifdef _WIN32
typedef HANDLE OSFILETYPE;
#else
#error port me
#endif
OSFILETYPE WFOPEN(const wchar_t *filename, OSFNCSTR mode, bool useFileReaders = true);
int FCLOSE(OSFILETYPE stream);
int FSEEK(OSFILETYPE stream, long offset, int origin);
uint64_t FTELL(OSFILETYPE stream);
#undef FREAD // defined on Mac for some reason
size_t FREAD(void *buffer, size_t size, size_t count, OSFILETYPE stream);
#undef FWRITE // defined on Mac for some reason
size_t FWRITE(const void *buffer, size_t size, size_t count, OSFILETYPE stream);
//char *FGETS( char *string, int n, OSFILETYPE stream);
//int FPRINTF(OSFILETYPE stream, const char *format , ...);
uint64_t FGETSIZE(OSFILETYPE stream);
const wchar_t *TMPNAM(wchar_t *string);
OSFNCSTR TMPNAM2(wchar_t *string, int val);
int FEXISTS(const char *filename); // return 1 if true, 0 if not, -1 if unknown
int UNLINK(const wchar_t *filename); // return 1 on success, 0 on error
int WACCESS(const wchar_t *filename, int mode);
#ifdef __cplusplus
// returns 1 on success, 0 on error, -1 if undoable deletes aren't supported
int FDELETE(OSFNCSTR filename, int permanently=TRUE);
#else
int FDELETE(OSFNCSTR filename, int permanently);
#endif
// 1 on success, 0 on fail
// can't move directories between volumes on win32
int MOVEFILE(OSFNCSTR filename, OSFNCSTR destfilename);
#ifdef __cplusplus
namespace StdFile {
#endif
int resolveShortcut(OSFNCSTR filename, OSFNSTR destfilename, int maxbuf);
#ifdef __cplusplus
};
#endif
#ifdef WASABI_COMPILE_FILEREADER
#ifndef REAL_STDIO
#ifndef __APPLE__
//#define fopen FOPEN
//#define fclose FCLOSE
//#define fseek FSEEK
//#define ftell FTELL
//#define fread FREAD
//#define fwrite FWRITE
//#define fgets FGETS
//#define fprintf FPRINTF
//#define unlink UNLINK
//#define access ACCESS
#endif
#endif //real_stdio
#endif //WASABI_COMPILE_FILEREADER
#endif //_nostudio
#endif

View File

@ -0,0 +1,51 @@
#include "precomp_wasabi_bfc.h"
#include "std_keyboard.h"
int Std::keyDown(int code)
{
#ifdef WIN32
return !!(GetKeyState(code) & 0x8000);
#elif defined(LINUX)
if ( code == MK_RBUTTON || code == MK_LBUTTON ) {
Window t1, t2;
int rx, ry, wx, wy;
unsigned int buttons;
XQueryPointer( Linux::getDisplay(), Linux::RootWin(), &t1, &t2,
&rx, &ry, &wx, &wy, &buttons );
if ( code == MK_RBUTTON )
return buttons & Button3Mask;
else
return buttons & Button1Mask;
}
int code1 = XKeysymToKeycode( Linux::getDisplay(), code & 0xFFFF );
int code2 = XKeysymToKeycode( Linux::getDisplay(), (code>>16) & 0xFFFF );
char keys_return[32] = {0};
XQueryKeymap( Linux::getDisplay(), keys_return );
if ( code1 && code2 )
return (keys_return[ (code1 >> 3) & 31 ] & (1 << (code1 & 7))) ||
(keys_return[ (code2 >> 3) & 31 ] & (1 << (code2 & 7)));
return (keys_return[ (code1 >> 3) & 31 ] & (1 << (code1 & 7)));
#else
return 0;
#warning port me!
#endif
}
// TODO: add async flag to be able to choose between GetKeyState/GetAsyncKeyState (win32) GetCurrentKeyModifiers/GetCurrentEventkeyModifiers (mac)
bool Std::keyModifier(int code)
{
#ifdef WIN32
return !!(GetKeyState(code) & 0x8000);
#elif defined(__APPLE__)
return GetCurrentKeyModifiers() & code;
#elif defined(LINUX)
#error port me
#endif
}

View File

@ -0,0 +1,46 @@
#ifndef NULLSOFT_WASABI_STD_KEYBOARD_H
#define NULLSOFT_WASABI_STD_KEYBOARD_H
#ifdef _WIN32
#include <windows.h>
enum
{
STDKEY_SHIFT = VK_SHIFT,
STDKEY_ALT = VK_MENU,
STDKEY_CONTROL = VK_CONTROL,
STDKEY_UP = VK_UP,
STDKEY_DOWN = VK_DOWN,
STDKEY_LEFT = VK_LEFT,
STDKEY_RIGHT = VK_RIGHT,
STDKEY_HOME = VK_HOME,
STDKEY_END = VK_END,
};
#elif defined(__APPLE__)
#include <Carbon/Carbon.h>
enum
{
STDKEY_SHIFT = shiftKey,
STDKEY_ALT = cmdKey, // yes, I know the option call has "alt" written on it, but Mac programs use Apple key like windows Alt key
STDKEY_CONTROL = controlKey,
STDKEY_UP = kUpArrowCharCode,
STDKEY_DOWN = kDownArrowCharCode,
STDKEY_LEFT = kLeftArrowCharCode,
STDKEY_RIGHT = kRightArrowCharCode,
STDKEY_HOME = kHomeCharCode,
STDKEY_END = kEndCharCode,
};
#else
#error port me
#endif
namespace Std
{
int keyDown(int code);
bool keyModifier(int code);
}
#endif

View File

@ -0,0 +1,18 @@
#include "precomp_wasabi_bfc.h"
#include "std_math.h"
void premultiplyARGB32(ARGB32 *words, int nwords)
{
for (; nwords > 0; nwords--, words++)
{
unsigned char *pixel = (unsigned char *)words;
unsigned int alpha = pixel[3];
if (alpha == 255) continue;
pixel[0] = (pixel[0] * alpha) >> 8; // blue
pixel[1] = (pixel[1] * alpha) >> 8; // green
pixel[2] = (pixel[2] * alpha) >> 8; // red
}
}

48
Src/Wasabi/bfc/std_math.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _STD_MATH_H
#define _STD_MATH_H
// FG> doesn't work for me without this include (error C2039: 'sin' : is not a member of '`global namespace'')
#include <math.h>
#include <bfc/platform/types.h>
#ifdef __cplusplus
static inline double SIN(double a) { return ::sin(a); }
static inline double COS(double a) { return ::cos(a); }
static inline double SQRT(double a) { return ::sqrt(a); }
#else
#define SIN(a) sin(a)
#define COS(a) sin(a)
#define SQRT(a) sqrt(a)
unsigned long COMEXP BSWAP_C(unsigned long input);
#endif
#ifdef __cplusplus
// neat trick from C++ book, p. 161
template<class T> inline T MAX(T a, T b) { return a > b ? a : b; }
template<class T> inline T MIN(T a, T b) { return a > b ? b : a; }
template<class T> inline T MINMAX(T a, T minval, T maxval) {
return (a < minval) ? minval : ( (a > maxval) ? maxval : a );
}
// and a couple of my own neat tricks :) BU
template<class T> inline T ABS(T a) { return a < 0 ? -a : a; }
template<class T> inline T SQR(T a) { return a * a; }
template<class T> inline int CMP3(T a, T b) {
if (a < b) return -1;
if (a == b) return 0;
return 1;
}
static inline RGB24 RGBTOBGR(RGB24 col) {
return ((col & 0xFF00FF00) | ((col & 0xFF0000) >> 16) | ((col & 0xFF) << 16));
}
static inline RGB24 BGRTORGB(RGB24 col) { return RGBTOBGR(col); }
static inline ARGB32 BGRATOARGB(ARGB32 col) { return RGBTOBGR(col); }
void premultiplyARGB32(ARGB32 *words, int nwords=1);
#else // not __cplusplus
void COMEXP premultiplyARGB32(ARGB32 *words, int nwords);
#endif
#endif

71
Src/Wasabi/bfc/std_mem.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef _STD_MEM_H
#define _STD_MEM_H
#include <bfc/platform/platform.h>
#include <string.h>
wchar_t *WMALLOC(size_t size);
void *MALLOC(size_t size);
void *CALLOC(size_t records, size_t recordsize);
void *REALLOC(void *ptr, size_t size);
void FREE(void *ptr);
void *MEMDUP(const void *src, size_t n);
void MEMCPY(void *dest, const void *src, size_t n);
void MEMCPY_(void *dest, const void *src, size_t n);
void MEMCPY32(void *dest, const void *src, size_t words);
#ifdef __cplusplus
static __inline int MEMCMP(const void *buf1, const void *buf2, size_t count) {
return memcmp(buf1, buf2, count);
}
static __inline void MEMSET(void *dest, int c, size_t n) {
memset(dest, c, n);
}
static __inline void MEMZERO(void *dest, size_t nbytes) {
memset(dest, 0, nbytes);
}
#else
#define MEMCMP memcmp
#define MEMSET memset
#define MEMZERO(dest, nbytes) memset(dest, 0, nbytes)
#endif
#ifdef __cplusplus
// these are for structs and basic classes only
static __inline void ZERO(int &obj) { obj = 0; }
template<class T>
inline void ZERO(T &obj) { MEMZERO(&obj, sizeof(T)); }
// generic version that should work for all types
template<class T>
inline void MEMFILL(T *ptr, T val, unsigned int n) {
for (int i = 0; i < n; i++) ptr[i] = val;
}
// asm 32-bits version
void MEMFILL32(void *ptr, unsigned long val, unsigned int n);
// helpers that call the asm version
template<>
inline void MEMFILL<unsigned long>(unsigned long *ptr, unsigned long val, unsigned int n) { MEMFILL32(ptr, val, n); }
template<>
void MEMFILL<unsigned short>(unsigned short *ptr, unsigned short val, unsigned int n);
// int
template<>
inline void MEMFILL<int>(int *ptr, int val, unsigned int n) {
MEMFILL32(ptr, *reinterpret_cast<unsigned long *>(&val), n);
}
// float
template<>
inline void MEMFILL<float>(float *ptr, float val, unsigned int n) {
MEMFILL32(ptr, *reinterpret_cast<unsigned long *>(&val), n);
}
#endif // __cplusplus defined
#endif

View File

@ -0,0 +1,11 @@
#ifndef _STD_MKNCC
#define _STD_MKNCC
// note: this is endian-incompatible with win32's MAKEFOURCC
// otoh, it shows up nicely in a debug register ;)
#define MK4CC(a, b, c, d) ( (((unsigned long)a)<<24)|(((unsigned long)b)<<16)|(((unsigned long)c)<<8)|((unsigned long)d) )
#define MK3CC(b, c, d) ( (((unsigned long)b)<<16)|(((unsigned long)c)<<8)|((unsigned long)d) )
#define MK2CC(c, d) ( (((unsigned long)c)<<8)|((unsigned long)d) )
#endif

View File

@ -0,0 +1,254 @@
#include "std_string.h"
#include <bfc/assert.h>
int WCSICOLL(const wchar_t *str1, const wchar_t *str2)
{
return lstrcmpiW(str1, str2);
}
int WCSICMP(const wchar_t *str1, const wchar_t *str2)
{
// WCSICMP is supposed to be used for string-lookup kinds of code, so we need to make sure it's done in a non-locale-aware way
return CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, str1, -1, str2, -1)-2;
//return _wcsicmp(str1, str2);
}
int WCSNICMP(const wchar_t *str1, const wchar_t *str2, size_t len)
{
return _wcsnicmp(str1, str2, len);
}
wchar_t *WCSTOK(wchar_t *str, const wchar_t *sep, wchar_t **last)
{
return wcstok(str, sep);
}
bool ISALPHA(wchar_t alpha)
{
return IsCharAlphaW(alpha)==TRUE;
}
bool ISDIGIT(wchar_t digit)
{
WORD type=0;
GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
return !!(type&C1_DIGIT);
}
bool ISSPACE(wchar_t space)
{
WORD type=0;
GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &space, 1, &type);
return !!(type&C1_SPACE);
}
bool ISPUNCT(wchar_t punct)
{
WORD type=0;
GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &punct, 1, &type);
return !!(type&C1_PUNCT);
}
char *STRSTR(const char *str1, const char *str2) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
ASSERT(str1 != str2);
return const_cast<char *>(strstr(str1, str2));
}
wchar_t *WCSCASESTR(const wchar_t *str1, const wchar_t *str2)
{
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
wchar_t *p;
size_t len = wcslen(str2);
for (p = (wchar_t *)str1; *p; p++)
{
if (!_wcsnicmp(p, str2, len))
return p;
}
return NULL;
}
void STRCPY(char *dest, const char *src) {
ASSERT(dest != NULL);
ASSERT(src != NULL);
ASSERT(dest != src);
strcpy(dest, src);
//INLINE
}
void STRNCPY(char *dest, const char *src, int maxchar) {
ASSERT(dest != NULL);
ASSERT(src != NULL);
strncpy(dest, src, maxchar);
//INLINE
}
void WCSCPYN(wchar_t *dest, const wchar_t *src, size_t maxchar)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
StringCchCopyW(dest, maxchar, src);
}
char *STRCHR(const char *str, int c) {
ASSERT(str != NULL);
return const_cast<char *>(strchr(str, c));
//INLINE
}
void STRCAT(char *dest, const char *append) {
ASSERT(dest != NULL);
ASSERT(append != NULL);
ASSERT(dest != append);
strcat(dest, append);
}
unsigned long STRTOUL(const char *s, char **p, int rx) {
ASSERT(s != NULL);
ASSERT(p != NULL);
return strtoul(s,p,rx);
}
wchar_t *WCSDUP(const wchar_t *ptr)
{
if (ptr == NULL) return NULL;
size_t size = wcslen(ptr);
wchar_t *ret = (wchar_t *)MALLOC((size + 1) * sizeof(wchar_t));
if (ret != NULL)
{
WCSCPYN(ret, ptr, size+1);
}
return ret;
}
int STRLEN(const char *str) {
ASSERT(str != NULL);
return (int)strlen(str);
}
int STRCMP(const char *str1, const char *str2) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
return strcmp(str1, str2);
}
int STRCMPSAFE(const char *str1, const char *str2, const char *defval1, const char *defval2) {
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return STRCMP(str1, str2);
}
int WCSCMPSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2) {
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return wcscmp(str1, str2);
}
int STRICMP(const char *str1, const char *str2) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
#if defined(WIN32)
return _stricmp(str1, str2);
#elif defined(LINUX)
return strcasecmp(str1, str2);
#endif
}
int STRICMPSAFE(const char *str1, const char *str2, const char *defval1, const char *defval2) {
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return STRICMP(str1, str2);
}
int WCSICMPSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2)
{
if (str1 == NULL) str1 = defval1;
if (str2 == NULL) str2 = defval2;
return WCSICMP(str1, str2);
}
int WCSEQLSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2) {
return !WCSCMPSAFE(str1, str2, defval1, defval2);
}
int STRCASEEQLSAFE(const char *str1, const char *str2, const char *defval1, const char *defval2) {
return !STRICMPSAFE(str1, str2, defval1, defval2);
}
int WCSCASEEQLSAFE(const wchar_t *str1, const wchar_t *str2, const wchar_t *defval1, const wchar_t *defval2)
{
return !WCSICMPSAFE(str1, str2, defval1, defval2);
}
//FG> sorry brennan, this need to not be a const :)
void STRTOUPPER(char *p)
{
CharUpperA(p);
}
void STRTOLOWER(char *p)
{
CharLowerA(p);
}
void WCSTOUPPER(wchar_t *p)
{
CharUpperW(p);
}
void KEYWORDUPPER(wchar_t *p)
{/*
if (p)
{
while (p && *p)
{
*p = towupper(*p);
p++;
}
}*/
int l = (int)wcslen(p);
// from MSDN - If LCMAP_UPPERCASE or LCMAP_LOWERCASE is set, the lpSrcStr and lpDestStr pointers can be the same.
LCMapStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), LCMAP_UPPERCASE, p, l, p, l);
}
void WCSTOLOWER(wchar_t *p)
{
CharLowerW(p);
}
int STRNICMP(const char *str1, const char *str2, int l) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
ASSERT(l>=0);
while (TOUPPER(*str1) == TOUPPER(*str2) && *str1 != 0 && *str2 != 0 && l--)
str1++, str2++;
if (l == 0) return 0;
return (*str2 - *str1);
}
int STRNCASEEQL(const char *str1, const char *str2, int l) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
return STRNICMP(str1, str2, l) == 0;
}
int STREQL(const char *str1, const char *str2) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
return (strcmp(str1, str2) == 0);
}
int STRCASEEQL(const char *str1, const char *str2) {
ASSERT(str1!=NULL);
ASSERT(str2!=NULL);
#ifdef WIN32
return (_stricmp(str1, str2)==0);
#else
return (strcasecmp(str1, str2)==0);
#endif
}

View File

@ -0,0 +1,11 @@
#ifndef _STD_STRING_H
#define _STD_STRING_H
#include <bfc/platform/platform.h>
#ifdef __cplusplus
bool ISALPHA(wchar_t alpha);
bool ISDIGIT(wchar_t digit);
bool ISSPACE(wchar_t space);
bool ISPUNCT(wchar_t punct);
#endif
#endif

1098
Src/Wasabi/bfc/std_wnd.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
#include "PathString.h"
#include <shlwapi.h>
PathString::PathString(const wchar_t *directory, const wchar_t *filename)
{
PathCombineW(path, directory, filename);
}

View File

@ -0,0 +1,21 @@
#ifndef NULLSOFT_BFC_PATHSTRING_H
#define NULLSOFT_BFC_PATHSTRING_H
#ifdef _WIN32
#include <windows.h>
class PathString
{
public:
PathString(const wchar_t *directory, const wchar_t *filename);
private:
wchar_t path[MAX_PATH];
};
#else
#error port me!
#endif
#endif

View File

@ -0,0 +1,783 @@
#include <bfc/wasabi_std.h>
#include <bfc/std_mem.h>
#include <bfc/nsguid.h>
#include "StringW.h"
#ifdef _WIN32
#include <shlwapi.h>
#endif
StringW::StringW(const wchar_t *initial_val)
: val(NULL)
{
setValue(initial_val);
}
StringW::StringW(const StringW &s)
: val(NULL)
{
if (s == NULL) setValue(NULL);
else setValue(s.getValue());
}
StringW::StringW(const StringW *s)
: val(NULL)
{
if (s == NULL) setValue(NULL);
else setValue(s->getValue());
}
StringW::~StringW()
{
FREE(val);
val = NULL;
}
int StringW::replaceNumericField(int value, wchar_t fieldchar)
{
if (val == NULL || *val == '\0') return 0;
int nrep = 0;
for (const wchar_t *p = val; *p; p++)
{
if (*p == fieldchar) nrep++;
else if (nrep) break;
}
if (nrep == 0) return 0; // no field found
StringW rc;
wchar_t fc[2] = { 0, 0 };
fc[0] = fieldchar;
for (int i = 0; i < nrep; i++) rc.cat(fc);
StringPrintfW fmt(L"%%0%0dd", nrep);
StringPrintfW replacement(fmt.getValue(), value);
return replace(rc, replacement);
}
// Returns index of first found, -1 if not found.
size_t StringW::lFindChar(wchar_t findval)
{
size_t length = len();
for (size_t i = 0; i != length; i++)
{
if (val[i] == findval)
{
return i;
}
}
return -1;
}
const wchar_t *StringW::setValue(const wchar_t *newval)
{
if (newval != val)
{
if ((unsigned long long)newval == NULL || ((unsigned long long)newval <= 65535))
{
FREE(val);
val = NULL;
}
else
{
if (val)
{
size_t len = wcslen(newval);
if (val != NULL)
#ifdef STRING_REALLOC_OPTIMS
{
size_t oldlen = wcslen(val);
// if smaller but greater than half previous size, don't realloc
if (len > oldlen || len < oldlen / 2)
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (len + 1));
}
#else
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (len + 1));
#endif
else
val = WMALLOC(len + 1);
ASSERT(newval != NULL);
MEMCPY_(val, newval, sizeof(wchar_t)*(len + 1));
}
else
val = WCSDUP(newval);
}
}
return getValue();
}
int StringW::isequal(const wchar_t *otherval) const
{
// TODO: benski> move to WCSCMPSAFE
if (!otherval)
otherval = L"";
if (!getValue())
return !wcscmp(L"", otherval);
else
return !wcscmp(getValue(), otherval);
}
int StringW::iscaseequal(const wchar_t *otherval) const
{
return !WCSICMPSAFE(getValue(), otherval);
}
int StringW::isempty() const
{
return (!val || !*val);
}
void StringW::toupper()
{
if (!isempty())
{
#ifdef _WIN32
CharUpperW(val);
#else
wchar_t *itr = val;
while (itr && *itr)
{
*itr = ::towupper(*itr);
itr++;
}
#endif
}
}
void StringW::tolower()
{
if (!isempty())
{
#ifdef _WIN32
CharLowerW(val);
#else
wchar_t *itr = val;
while (itr && *itr)
{
*itr = ::towlower(*itr);
itr++;
}
#endif
}
}
const wchar_t *StringW::getValueSafe(const wchar_t *def_val) const
{
if (val == NULL)
return def_val;
else
return val;
}
const wchar_t *StringW::cat(const wchar_t *value)
{
if (value == NULL || *value == 0)
return getValue();
if (val == NULL)
return setValue(value);
return catn(value, wcslen(value));
}
const wchar_t *StringW::catn(const wchar_t *value, size_t len)
{
if (len == 0) return val;
if (value == NULL || *value == 0) return getValue();
if (val == NULL) return ncpy(value, len);
size_t ol = wcslen(val);
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (ol + len + 1));
val[ol + len] = 0;
wcsncpy(val + ol, value, len);
return val;
}
// replaces string with n chars of val or length of val, whichever is less.
const wchar_t *StringW::ncpy(const wchar_t *newstr, size_t numchars)
{
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (numchars + 1));
val[numchars] = 0;
wcsncpy(val, newstr, numchars);
return getValue();
}
// swaps buffers with another string
void StringW::swap(StringW *swapper)
{
wchar_t *tempChar = swapper->val;
swapper->val = val;
val = tempChar;
}
void StringW::swap(StringW &swapper) // swaps buffers with another string
{
wchar_t *tempChar = swapper.val;
swapper.val = val;
val = tempChar;
}
// take ownership of a buffer
void StringW::own(wchar_t *swapper)
{
if (val)
FREE(val);
val = swapper;
}
const wchar_t *StringW::catPostSeparator(const wchar_t *value, const wchar_t separator)
{
if (value == NULL || *value == 0 || separator == 0) return getValue();
size_t oldLen = val ? wcslen(val) : 0;
size_t newLen = wcslen(value);
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (oldLen + newLen + 1 + 1)); // +1 for separator, +1 for null character
wcsncpy(val + oldLen, value, newLen + 1);
val[oldLen + newLen] = separator; // add the separator
val[oldLen + newLen + 1] = 0; // null terminate
return val;
}
size_t StringW::va_sprintf(const wchar_t *format, va_list args)
{
if (!format) return 0;
va_list saveargs = args;
// roughly evaluate size of dest string
const wchar_t *p = format;
size_t length = 0;
while (p && *p)
{
if (*(p++) != '%') length++;
else
{
void *arg = va_arg(args, void *);
for (;;)
{
const wchar_t f = *p++;
if (f == 'c') length++;
else if (f == 'i') length += 16;
else if (f == 'u') length += 16;
else if (f == 'f') length += 64;
else if (f == 'd' || f == 'f') length += 64;
else if (f == 'x') length += 32; // Hex with LC Alphas: 0x0009a64c
else if (f == 'X') length += 32; // Hex with UC Alphas: 0x0009A64C
else if (f == 's')
{ // ::vsrintf can properly handle null.
if (arg == NULL)
{
length += wcslen(L"(null)"); // Just to be explicit.
}
else
{
length += wcslen((const wchar_t *)arg);
}
}
else if (f == 'S') // uppercase S mean narrow string
{ // ::vsrintf can properly handle null.
if (arg == NULL)
{
length += STRLEN("(null)"); // Just to be explicit.
}
else
{
length += STRLEN((const char *)arg);
}
}
else if (ISDIGIT(f)) continue;
else if (f == '.') continue;
else if (f == '%') length++;
else ASSERTPR(0, "undefined format passed to stringprintf!");
break;
}
}
}
if (val)
{
if (len() < length)
val = (wchar_t *)REALLOC(val, sizeof(wchar_t) * (length + 1));
}
else
val = WMALLOC(length + 1);
// now write the string in val
#ifdef _WIN32
size_t remain;
StringCchVPrintfExW(val, length+1, 0, &remain, 0, format, saveargs);
return length-remain;
#elif defined(__APPLE__)
int real_len = ::vswprintf(val, length+1, format, saveargs);
ASSERTPR(real_len <= (int)length, "String.printf overflow");
return real_len;
#endif
}
size_t StringW::len() const
{
return (val == NULL) ? 0 : wcslen(val);
}
void StringW::trunc(int newlen)
{
if (val)
{
int oldlen = (int)wcslen(val);
if (newlen < 0) newlen = MAX(oldlen + newlen, 0);
int trimLen = MIN(oldlen, newlen);
val[trimLen] = 0;
}
}
int StringW::lastChar()
{
if (isempty()) return -1;
return val[len() - 1];
}
const wchar_t *StringW::prepend(const wchar_t *value)
{
if (value == NULL || *value == 0) return getValue();
if (val == NULL) return setValue(value);
StringPrintfW temp(L"%s%s", value, getValue());
swap(&temp);
return getValue();
}
int StringW::replace(const wchar_t *find, const wchar_t *replace)
{
if (len() == 0 || find == NULL || replace == NULL) return 0;
int find_count = 0;
wchar_t *p, *p2;
size_t rep_len = wcslen(replace);
size_t find_len = wcslen(find);
ptrdiff_t size_diff = rep_len - find_len;
if ( size_diff == 0 )
{
p = val;
while ( p = wcsstr( p, find ) )
{
wcsncpy( p, replace, rep_len );
p += find_len;
find_count++;
}
}
else
{
wchar_t *new_buf, *in;
p = val;
while ( p = wcsstr( p, find ) )
{
find_count++;
p += find_len;
}
int length = (int)( len() + find_count * size_diff + 1 );
new_buf = (wchar_t *)MALLOC(sizeof(wchar_t) * length);
p = val;
in = new_buf;
while ( p2 = wcsstr( p, find ) )
{
wcsncpy( in, p, p2 - p );
in += p2 - p;
wcsncpy( in, replace, rep_len );
in += rep_len;
p = p2 + find_len;
}
wcscpy( in, p );
new_buf[ len() + find_count * size_diff ] = 0;
// just swap buffers
FREE(val);
val = new_buf;
}
return find_count;
}
const wchar_t *StringW::printf(const wchar_t *format, ...)
{
va_list args;
va_start (args, format);
va_sprintf(format, args);
va_end(args);
return getValue();
}
void StringW::AppendPath(const wchar_t *path)
{
FixSlashes();
if (val)
{
#ifdef _WIN32
wchar_t temp[MAX_PATH] = {0};
PathCombineW(temp, val, path);
setValue(temp);
#else
#warning find a better way
wchar_t temp[PATH_MAX] = {0};
swprintf(temp, PATH_MAX, L"%s%s", val, path);
setValue(temp);
#endif
}
else
setValue(path);
}
void StringW::AppendFolder(const wchar_t *path)
{
#ifdef _WIN32
FixSlashes();
wchar_t temp[MAX_PATH] = {0};
if (val)
PathCombineW(temp, val, path);
else
WCSCPYN(temp, path, MAX_PATH);
PathAddBackslashW(temp);
setValue(temp);
#else
#warning find a better way
wchar_t temp[PATH_MAX] = {0};
swprintf(temp, PATH_MAX, L"%s%s/", val, path);
setValue(temp);
#endif
}
void StringW::AddBackslash()
{
FixSlashes();
if (val)
{
#ifdef _WIN32
wchar_t temp[MAX_PATH] = {0};
WCSCPYN(temp, val, MAX_PATH);
PathAddBackslashW(temp);
#else
wchar_t temp[PATH_MAX] = {0};
WCSCPYN(temp, val, PATH_MAX);
wcscat(temp, L"/");
#warning port me
#endif
setValue(temp);
}
}
void StringW::changeChar(wchar_t from, wchar_t to)
{
if (val == NULL) return ;
size_t length = len();
for (size_t i = 0; i != length; i++)
if (val[i] == from) val[i] = to;
}
void StringW::RemovePath()
{
#ifdef _WIN32
// benski> the OS-level function fucks up if there are forward slashes, so we'll fix it
// TODO: remove eventually
FixSlashes();
if (val)
PathRemoveFileSpecW(val);
#else
#warning port me
#endif
}
void StringW::purge()
{
FREE(val);
val = NULL;
}
StringW StringW::rSplitChar(const wchar_t *findval)
{
if (val == NULL) return StringW();
// The index of the found character
size_t idxval = rFindChar(findval);
return rSplit(idxval);
}
// Same as above, save the "findval" is a string where it searches
// for any of the characters in the string.
size_t StringW::rFindChar(const wchar_t *findval)
{
size_t length = len();
size_t numchars = wcslen(findval);
for (size_t i = length - 1; i > 0; i--)
{
for (size_t j = 0; j != numchars; j++)
{
if (val[i] == findval[j])
{
return i;
}
}
}
return -1;
}
StringW StringW::lSplitChar(const wchar_t *findval)
{
if (val == NULL) return StringW();
// The index of the found character
size_t idxval = lFindChar(findval);
return lSplit(idxval);
}
// Same as above, save the "findval" is a string where it searches
// for any of the characters in the string.
size_t StringW::lFindChar(const wchar_t *findval)
{
size_t length = len();
size_t numchars = wcslen(findval);
for (size_t i = 0; i != length; i++)
{
for (size_t j = 0; j != numchars; j++)
{
if (val[i] == findval[j])
{
return i;
}
}
}
return -1;
}
StringW StringW::rSplit(size_t idxval)
{
if (val == NULL) return StringW();
if (idxval == -1)
{ // Not Found
// Copy our contents to return on the stack
StringW retval(val);
// And zero the string.
val[0] = 0;
return retval;
}
else
{
// Copy from the found index downwards to the retval
StringW retval(val + idxval);
// Terminate the found char index
val[idxval] = 0;
// That was easier, wasn't it?
return retval;
}
}
// Splits string at findval. Characters passed by search, including the
// found character, are MOVED to the returned string. If there is no char
// to be found, the entire string is returnef and the called instance is
// left empty. (Makes looped splits very easy).
StringW StringW::lSplit(size_t idxval)
{
if (val == NULL) return StringW();
if (idxval == -1)
{ // Not Found
// Copy our contents to return on the stack
StringW retval(val);
// And zero the string.
if (val)
{
val[0] = 0;
}
return retval;
}
else
{
StringW retval;
// Copy into retval the number of characters to the found char index.
retval.ncpy(val, idxval + 1);
{
StringW testscope;
// Copy into retval the number of characters to the found char index.
testscope.ncpy(val, idxval + 1);
}
#if USE == FAST_METHODS
size_t len = wcslen(val + idxval + 1);
MEMCPY(val, val + idxval + 1, sizeof(wchar_t)*(len + 1));
#elif USE == SAFE_METHODS
// Copy from the found index downwards to save for this object
StringW temp(val + idxval + 1);
// And then copy into ourselves the tempspace.
*this = temp;
#endif
return retval;
}
}
// Same as split, except the find char is cut completely.
StringW StringW::lSpliceChar(const wchar_t *findval)
{
if (val == NULL) return StringW();
//CUT // Auto-scope reference allows us to avoid a copy.
//CUT String & retval = lSplitChar(findval);
//BU gcc doesn't agree with you and neither do I :/
StringW retval = lSplitChar(findval);
// We need to strip the findval char, which is the end char.
size_t end = retval.len();
size_t num = wcslen(findval);
if (end)
{
for (size_t i = 0; i != num; i++)
{
if (retval.val[end - 1] == findval[i])
{
retval.val[end - 1] = 0;
}
}
}
return retval;
}
StringW StringW::rSpliceChar(const wchar_t *findval)
{
if (val == NULL) return StringW();
//CUT // Auto-scope reference allows us to avoid a copy.
//CUT String & retval = rSplitChar(findval);
//BU gcc doesn't agree with you and neither do I :/
StringW retval = rSplitChar(findval);
// We need to strip the findval char, which is the first char.
// (But we still check for empty string:)
size_t end = retval.len();
size_t num = wcslen(findval);
if (end)
{
for (size_t i = 0; i != num; i++)
{
if (retval.val[0] == findval[i])
{
#if USE == FAST_METHODS
size_t len = wcslen(retval.val + 1);
MEMCPY(retval.val, retval.val + 1, sizeof(wchar_t)*(len + 1));
#elif USE == SAFE_METHODS
StringW temp(retval.val + 1);
retval = temp;
#endif
return retval;
}
}
}
return retval;
}
void StringW::FixSlashes()
{
if (val)
{
wchar_t *itr = val;
while (itr && *itr)
{
if (*itr == '\\' || *itr == '/')
*itr = Wasabi::Std::dirChar();
#ifdef _WIN32
itr = CharNextW(itr);
#else
itr++;
#endif
}
}
}
/* ------------ */
StringPrintfW::StringPrintfW(const wchar_t *format, ...)
{
va_list args;
va_start (args, format);
va_sprintf(format, args);
va_end(args);
}
StringPrintfW::StringPrintfW(int value)
{
*this += value;
}
StringPrintfW::StringPrintfW(double value)
{
// TODO: review to use locale variant...
wchar_t* locale = _wcsdup(_wsetlocale(LC_NUMERIC, NULL));
_wsetlocale(LC_NUMERIC, L"C");
*this += StringPrintfW(L"%f", value);
if (locale)
{
_wsetlocale(LC_NUMERIC, locale);
free(locale);
}
}
StringPrintfW::StringPrintfW(GUID g)
{
wchar_t splab[nsGUID::GUID_STRLEN + 1] = {0};
nsGUID::toCharW(g, splab);
cat(splab);
}
/* ------------ */
int StringWComparator::compareItem(StringW *p1, StringW* p2)
{
return wcscmp(p1->getValue(), p2->getValue());
}
int StringWComparator::compareAttrib(const wchar_t *attrib, StringW *item)
{
return wcscmp(attrib, item->getValue());
}
/* ------------ */
_DebugStringW::_DebugStringW(const wchar_t *format, ...)
{
va_list args;
va_start (args, format);
va_sprintf(format, args);
va_end(args);
debugPrint();
}
void _DebugStringW::debugPrint()
{
#ifdef _WIN32
OutputDebugStringW(getValue());
if (lastChar() != L'\n') OutputDebugStringW(L"\n");
#else
#warning port me
#endif
}
StringPathCombine::StringPathCombine(const wchar_t *path, const wchar_t *filename)
{
#ifdef _WIN32
wchar_t temp[MAX_PATH] = {0};
PathCombineW(temp, path, filename);
setValue(temp);
#else
setValue(path);
AppendPath(filename);
#endif
}
// StringW operators using StringPrintf
const wchar_t *StringW::operator +=(wchar_t value)
{
wchar_t add[2]={value, 0};
return cat(add);
// the "Fast" methods and the Printf be
// built off of that?
}
const wchar_t *StringW::operator +=(int value)
{
wchar_t num[64] = {0};
#ifdef _WIN32
_itow(value, num, 10);
#else
WCSNPRINTF(num, 64, L"%d", value);
#endif
return cat(num);
}
const wchar_t *StringW::operator +=(GUID guid)
{
wchar_t guidstr[64] = {0};
nsGUID::toCharW(guid, guidstr);
return cat(guidstr);
}

View File

@ -0,0 +1,467 @@
#ifndef _STRINGW_H_WASABI
#define _STRINGW_H_WASABI
#ifdef __cplusplus
/**
This is a very basic string class. It is not trying to be a be-all end-all
string class. It's meant to be just enough functionality to avoid STRDUP().
It is available to use in client apps, but no API in Wasabi depends on its
use by client code, so you can ignore it if you like. ;)
Also note that one of the design goals is to use same storage space as
a char *, which means no virtual methods.
@short Basic string class, to replace STRDUP/FREE
@see StringPrintf
@see DebugString
*/
#include <bfc/platform/types.h>
class StringW
{
public:
StringW(const wchar_t *initial_val = NULL);
StringW(const StringW &s);
StringW(const StringW *s);
~StringW();
/**
Returns the value of the string. It is a pointer to the internal storage
used by the class, so you must not assume the pointer will not change,
because it will.
@see getValueSafe();
@ret The value of the string.
*/
const wchar_t *getValue() const { return val; }
const wchar_t *v() const { return getValue(); } // for ease of typing
operator const wchar_t *() const { return getValue(); }
/**
Gets the value of the string, or a safe value if the value is NULL.
@param def_val The value to return if the string's value is NULL. Defaults to "".
@see getValue()
@ret The value of the string, or a safe value if the value is NULL.
*/
const wchar_t *getValueSafe(const wchar_t *def_val = L"") const; // returns def_val if NULL
/**
Returns the value of the character at a position in the string. If the
position is invalid, returns -1. Note that unless bounds_check is set to
TRUE, the pos will only be checked for negative values.
@param pos The position of the character to return.
@param bounds_check If TRUE, pos is checked against the length of the string.
@see setChar()
@ret The value of the character at the position in the string, or -1 if the position is invalid.
*/
//int getChar(int pos, int bounds_check = FALSE);
/**
Sets the value of the character at a position in the string. Not multibyte UTF-8 safe yet. No lengthwise bounds checking yet.
@param pos The position to set.
@param value The value to set.
@ret The value of the character set, or -1 if pos < 0.
*/
//int setChar(int pos, int value);
/**
Sets the value of the string. The given value will be copied.
Can accept NULL. Note that this may cause the
pointer returned by getValue() et al to change.
@param newval The new value of the string, nul-terminated.
@ret The new value of the string.
@see getValue()
*/
const wchar_t *setValue(const wchar_t *newval);
/**
Gets the value of the string in the form of a non-const wchar_t *. WARNING: you
don't usually need to call this. If you want to modify the string,
you can generally just use setChar(), or setValue().
@ret The value of the string, casted to a non-const wchar_t *.
@see getValue()
@see setValue();
@see setChar();
*/
wchar_t *getNonConstVal() { return const_cast<wchar_t *>(getValue()); }
const wchar_t *operator =(const wchar_t *newval) { return setValue(newval); }
const wchar_t *operator +=(const wchar_t *addval)
{
return cat(addval);
}
const wchar_t *operator +=(wchar_t value);
const wchar_t *operator +=(int value);
const wchar_t *operator +=(GUID guid);
// copy assignment operator
StringW &operator =(const StringW &s)
{
if (this != &s)
setValue(s);
return *this;
}
// comparator operators
//inline int operator ==(const wchar_t *val) const
//{
// if (!val) return isempty();
// return isequal(val);
//}
//inline int operator <(const wchar_t *val) const
//{
// return islessthan(val);
//}
//inline int operator !=(const wchar_t *val) const
//{
// if (!val) return !isempty();
// return !isequal(val);
//}
//inline int operator >(const wchar_t *val) const
//{
// return (!islessthan(val)) && (!isequal(val));
//}
inline StringW operator +(const wchar_t *val)
{
StringW retval = *this;
return retval += val;
}
//inline int operator ==(const StringW &val) const
//{
// return isequal(val);
//}
//inline int operator <(const StringW &val) const
//{
// return islessthan(val);
//}
//inline int operator !=(const StringW &val) const
//{
// return !isequal(val);
//}
//inline int operator >(const StringW &val) const
//{
// return (!islessthan(val)) && (!isequal(val));
//}
//inline StringW operator +(const StringW &val)
//{
// StringW retval = *this;
// return retval += val;
//}
//inline StringW operator +(const wchar_t val)
//{
// StringW retval = *this;
// return retval += val;
//}
/**
Gets the length of the string's value. Note that a 0 length can result from
both a value of NULL and a value of "".
@ret The length of the string's value;
*/
size_t len() const;
/**
Returns TRUE if the string's value is either NULL or "".
@ret TRUE if the string's value is either NULL or "", FALSE otherwise.
*/
int isempty() const;
/**
Converts entire string to uppercase. Not multibyte UTF-8 safe yet.
@see tolower()
*/
void toupper();
/**
Converts entire string to lowercase. Not multibyte UTF-8 safe yet.
@see tolower()
*/
void tolower();
/**
Checks string value equality against a nul-terminated wchar_t *.
@param otherval The value to check against. If NULL, will be treated as "".
@ret TRUE if the string matches exactly, FALSE otherwise.
@see iscaseequal()
@see islessthan()
*/
int isequal(const wchar_t *otherval) const; // basically !strcmp
/**
Checks string value equality against a nul-terminated wchar_t *, case insensitively. I.e. "Blah" is case equal to "bLaH".
@param otherval The value to check against. If NULL, will be treated as "".
@ret TRUE if the string matches case-insensitively, FALSE otherwise.
@see isequal()
@see islessthan()
*/
int iscaseequal(const wchar_t *otherval) const; // basically !strcasecmp
//int islessthan(const wchar_t *otherval) const; // basically strcmp < 0
/**
Changes all instances of a character to another character throughout the
string. Not multibyte UTF-8 aware yet. Note you can use a 'to' of NULL,
but this practice is not encouraged: try to use trunc() or truncateOnChar() instead.
@param from The character value to modify.
@param to The character value to replace with.
@see trunc()
@see truncateOnChar()
*/
void changeChar(wchar_t from, wchar_t to);
/**
Truncates the string value at the first given character value found. If fromright==TRUE, searches from the right, otherwise goes left-to-right. Not UTF-8 multibyte aware yet.
Ex:
StringW x("abcd");
x.truncateOnChar('c');
x now contains "ab"
@see changeChar()
*/
//void truncateOnChar(int which, int fromright = FALSE);
/**
Gets the last character value (rightmost).
@see getChar()
@ret The rightmost character value, or -1 if string is empty.
*/
int lastChar(); // -1 if empty
/**
Executes a standard printf type call and sets the string's value to it.
@ret The new value of the string.
@param format The formatting string to use.
*/
const wchar_t *printf(const wchar_t *format, ...);
/**
Concatenates the given value onto the end of the string. NULL will be
treated as "".
@param value The value to concatenate.
@ret The new value of the string.
@see catn()
@see prepend()
*/
const wchar_t *cat(const wchar_t *value);
/**
Concatenates a certain number of characters from the given value onto the end of the string. NULL will be treated as "".
@param value The value to concatenate.
@param len How many characters of value to use.
@ret The new value of the string.
@see cat()
@see prepend()
*/
const wchar_t *catn(const wchar_t *value, size_t len);
/**
Useful for making directory paths and stuff
adds a string plus a separator character.
i.e.
StringW x = "/usr/";
x.catPostSeparator("bin", '/');
creates "/usr/bin/"
*/
const wchar_t *catPostSeparator(const wchar_t *value, const wchar_t separator);
/**
similiar to above, but puts the separator first
i.e.
StringW x = "/usr";
x.catPostSeparator('/' "bin");
creates "/usr/bin"
*/
//const wchar_t *catPreSeparator(const wchar_t separator, const wchar_t *value);
/**
Inserts the given string value at the beginning of the string. NULL will be
treated as "".
@param value The value to insert.
@ret The new value of the string.
@see cat()
@see catn()
*/
const wchar_t *prepend(const wchar_t *value);
// replaces string with n chars of val or length of val, whichever is less.
const wchar_t *ncpy(const wchar_t *newstr, size_t numchars);
/**
Copies up to maxlen chars from the string into the destination. Differs from
STRNCPY in that it makes sure the destination is always nul-terminated, so
note that maxlen includes the terminating nul.
@param dest The destination to copy to.
@param maxlen How many bytes, at most, to copy.
*/
//void strncpyTo(wchar_t *dest, int maxlen);
// -----------------------------------------
// Character based find-n-splice methods --
// "l" and "r" prefixes specify to begin at
// front or back of string:
// Returns index of first found, -1 if not found.
size_t lFindChar(wchar_t findval);
size_t lFindChar(const wchar_t *findval); // a list of chars to search for
//int rFindChar(wchar_t findval);
size_t rFindChar(const wchar_t *findval); // a list of chars to search for
// Splits string at findval. Characters passed by search, including the
// found character, are MOVED to the returned string. If there is no wchar_t
// to be found, the entire string is returned and the called instance is
// left empty. (Makes looped splits very easy).
StringW lSplit(size_t idxval);
//StringW lSplitChar(wchar_t findval);
StringW lSplitChar(const wchar_t *findval);
StringW rSplit(size_t idxval);
//StringW rSplitChar(wchar_t findval);
StringW rSplitChar(const wchar_t *findval);
// Same as split, except the find wchar_t is cut completely.
//StringW lSpliceChar(wchar_t findval);
StringW lSpliceChar(const wchar_t *findval);
//StringW rSpliceChar(wchar_t findval);
StringW rSpliceChar(const wchar_t *findval);
/**
Replaces all occurences of the value specified by 'find' with the value
specified by 'replace'.
@param find The value to find.
@param replace The value to replace with.
@ret The number of replacements that were executed.
*/
int replace(const wchar_t *find, const wchar_t *replace);
/**
Replaces fields of same character with 0-padded text representation of an int.
Example: blah$$$$.png becomes blah0000.png
*/
int replaceNumericField(int value, wchar_t fieldchar = '\x24');
// UTF8-Aware "Character Based" Methods
/**
Returns how many characters are in the string value. Same as len(), but multibyte UTF-8 aware.
@see len()
@ret Number of logical UTF-8 character in the string.
*/
//int numCharacters();
/**
Truncates the length of the string to newlen. If newlen is negative, trims
-newlen characters from the end. Multibyte UTF-8 aware.
@param newlen The new length of the string. If the string is shorter than this, nothing happens. If this value is negative, then the absolute value of newlen is how many characters to trim from the right. I.e. -1 means trim off one character from the end.
@see truncateOnChar()
*/
void trunc(int newlen);
// void trim(const wchar_t *whitespace = " \t\r\n", int left = TRUE, int right = TRUE);
/**
Does a vsprintf. Used the same way as printf(), but with a va_list instead of "...".
@param format The format string to use.
@param args The argument list in va_list format.
@ret The number of characters in the final string.
*/
size_t va_sprintf(const wchar_t *format, va_list args);
/**
Ensures that the string drops any memory it might have allocated.
*/
void purge();
void swap(StringW *); // swaps buffers with another string
void swap(StringW &); // swaps buffers with another string
void own(wchar_t *); // take ownership of a buffer
void AppendPath(const wchar_t *path);
void AppendFolder(const wchar_t *path);
void AddBackslash();
void RemovePath();
void FixSlashes();
protected:
wchar_t * val;
enum { wastage_allowed = 128 };
};
class StringPathCombine : public StringW
{
public:
StringPathCombine(const wchar_t *path, const wchar_t *filename);
};
/**
StringW class with a printf-style constructor. Otherwise identical to StringW.
Also takes some standard types, like int, double, and GUID.
@see GUID
@see StringW
*/
class StringPrintfW : public StringW
{
public:
StringPrintfW(const wchar_t *format = NULL, ...);
StringPrintfW(int value);
StringPrintfW(double value);
StringPrintfW(GUID g);
};
#if defined(NDEBUG) && defined(WASABI_NO_RELEASEMODE_DEBUGSTRINGS)
#define DebugStringW __noop
#else
#define DebugStringW _DebugStringW
#endif
class _DebugStringW : public StringW
{
public:
_DebugStringW(const wchar_t *format = NULL, ...);
_DebugStringW(const StringW &s);
_DebugStringW(const StringW *s);
void debugPrint();
};
#if 0
class StringToLower : public StringW
{
public:
StringToLower(const char *val = NULL) : StringW(val)
{
tolower();
}
};
class StringToUpper : public StringW
{
public:
StringToUpper(const char *val = NULL) : StringW(val)
{
toupper();
}
};
//
// Global operator overrides to allow string to take over for
// the use of standard operators with const char pointers as
// left hand operands.
inline int operator ==(const char *v1, const StringW &v2)
{
return v2.isequal(v1);
}
inline int operator !=(const char *v1, const StringW &v2)
{
return !v2.isequal(v1);
}
inline int operator <(const char *v1, const StringW &v2)
{
return !v2.islessthan(v1);
}
inline int operator >(const char *v1, const StringW &v2)
{
return v2.islessthan(v1);
}
#endif
/**
Compares two strings. Generally used with PtrListSorted<>
@see PtrListSorted
*/
class StringWComparator
{
public:
// comparator for sorting
static int compareItem(StringW *p1, StringW* p2);
// comparator for searching
static int compareAttrib(const wchar_t *attrib, StringW *item);
};
#endif
#endif // __cplusplus

View File

@ -0,0 +1,473 @@
#ifndef _STRING_H_WASABI
#define _STRING_H_WASABI
#ifdef __cplusplus
/**
This is a very basic string class. It is not trying to be a be-all end-all
string class. It's meant to be just enough functionality to avoid STRDUP().
It is available to use in client apps, but no API in Wasabi depends on its
use by client code, so you can ignore it if you like. ;)
Also note that one of the design goals is to use same storage space as
a char *, which means no virtual methods.
@short Basic string class, to replace STRDUP/FREE
@see StringPrintf
@see DebugString
*/
#include <bfc/platform/types.h>
//#include <bfc/std.h>
#include <stdarg.h>
class String
{
public:
String(const char *initial_val = NULL);
String(const String &s);
String(const String *s);
~String();
/**
Returns the value of the string. It is a pointer to the internal storage
used by the class, so you must not assume the pointer will not change,
because it will.
@see getValueSafe();
@ret The value of the string.
*/
const char *getValue() const { return val; }
const char *v() const { return getValue(); } // for ease of typing
operator const char *() const { return getValue(); }
/**
Gets the value of the string, or a safe value if the value is NULL.
@param def_val The value to return if the string's value is NULL. Defaults to "".
@see getValue()
@ret The value of the string, or a safe value if the value is NULL.
*/
const char *getValueSafe(const char *def_val = "") const; // returns def_val if NULL
/**
Returns the value of the character at a position in the string. If the
position is invalid, returns -1. Note that unless bounds_check is set to
TRUE, the pos will only be checked for negative values.
@param pos The position of the character to return.
@param bounds_check If TRUE, pos is checked against the length of the string.
@see setChar()
@ret The value of the character at the position in the string, or -1 if the position is invalid.
*/
int getChar(int pos, int bounds_check = false);
/**
Sets the value of the character at a position in the string. Not multibyte UTF-8 safe yet. No lengthwise bounds checking yet.
@param pos The position to set.
@param value The value to set.
@ret The value of the character set, or -1 if pos < 0.
*/
int setChar(int pos, int value);
/**
Sets the value of the string. The given value will be copied.
Can accept NULL. Note that this may cause the
pointer returned by getValue() et al to change.
@param newval The new value of the string, nul-terminated.
@ret The new value of the string.
@see getValue()
*/
const char *setValue(const char *newval);
/**
Gets the value of the string in the form of a non-const char *. WARNING: you
don't usually need to call this. If you want to modify the string,
you can generally just use setChar(), or setValue().
@ret The value of the string, casted to a non-const char *.
@see getValue()
@see setValue();
@see setChar();
*/
char *getNonConstVal() { return const_cast<char *>(getValue()); }
const char *operator =(const char *newval) { return setValue(newval); }
const char *operator +=(const char *addval)
{
return cat(addval);
}
const char *operator +=(char value);
const char *operator +=(int value);
const char *operator +=(GUID guid);
// copy assignment operator
String &operator =(const String &s)
{
if (this != &s)
setValue(s);
return *this;
}
// comparator operators
inline int operator ==(const char *val) const
{
if (!val) return isempty();
return isequal(val);
}
inline int operator <(const char *val) const
{
return islessthan(val);
}
inline int operator !=(const char *val) const
{
if (!val) return !isempty();
return !isequal(val);
}
inline int operator >(const char *val) const
{
return (!islessthan(val)) && (!isequal(val));
}
inline String operator +(const char *val)
{
String retval = *this;
return retval += val;
}
inline int operator ==(const String &val) const
{
return isequal(val);
}
inline int operator <(const String &val) const
{
return islessthan(val);
}
inline int operator !=(const String &val) const
{
return !isequal(val);
}
inline int operator >(const String &val) const
{
return (!islessthan(val)) && (!isequal(val));
}
inline String operator +(const String &val)
{
String retval = *this;
return retval += val;
}
inline String operator +(const char val)
{
String retval = *this;
return retval += val;
}
/**
Gets the length of the string's value. Note that a 0 length can result from
both a value of NULL and a value of "".
@ret The length of the string's value;
*/
int len() const;
/**
Returns TRUE if the string's value is either NULL or "".
@ret TRUE if the string's value is either NULL or "", FALSE otherwise.
*/
int isempty() const;
/**
Converts entire string to uppercase. Not multibyte UTF-8 safe yet.
@see tolower()
*/
void toupper();
/**
Converts entire string to lowercase. Not multibyte UTF-8 safe yet.
@see tolower()
*/
void tolower();
/**
Checks string value equality against a nul-terminated char *.
@param otherval The value to check against. If NULL, will be treated as "".
@ret TRUE if the string matches exactly, FALSE otherwise.
@see iscaseequal()
@see islessthan()
*/
int isequal(const char *otherval) const; // basically !strcmp
/**
Checks string value equality against a nul-terminated char *, case insensitively. I.e. "Blah" is case equal to "bLaH".
@param otherval The value to check against. If NULL, will be treated as "".
@ret TRUE if the string matches case-insensitively, FALSE otherwise.
@see isequal()
@see islessthan()
*/
int iscaseequal(const char *otherval) const; // basically !strcasecmp
int islessthan(const char *otherval) const; // basically strcmp < 0
/**
Changes all instances of a character to another character throughout the
string. Not multibyte UTF-8 aware yet. Note you can use a 'to' of NULL,
but this practice is not encouraged: try to use trunc() or truncateOnChar() instead.
@param from The character value to modify.
@param to The character value to replace with.
@see trunc()
@see truncateOnChar()
*/
void changeChar(int from, int to);
/**
Truncates the string value at the first given character value found. If fromright==TRUE, searches from the right, otherwise goes left-to-right. Not UTF-8 multibyte aware yet.
Ex:
String x("abcd");
x.truncateOnChar('c');
x now contains "ab"
@see changeChar()
*/
void truncateOnChar(int which, int fromright = false);
/**
Gets the last character value (rightmost).
@see getChar()
@ret The rightmost character value, or -1 if string is empty.
*/
int lastChar(); // -1 if empty
/**
Executes a standard printf type call and sets the string's value to it.
@ret The new value of the string.
@param format The formatting string to use.
*/
const char *printf(const char *format, ...);
/**
Concatenates the given value onto the end of the string. NULL will be
treated as "".
@param value The value to concatenate.
@ret The new value of the string.
@see catn()
@see prepend()
*/
const char *cat(const char *value);
/**
Concatenates a certain number of characters from the given value onto the end of the string. NULL will be treated as "".
@param value The value to concatenate.
@param len How many characters of value to use.
@ret The new value of the string.
@see cat()
@see prepend()
*/
const char *catn(const char *value, int len);
/**
Useful for making directory paths and stuff
adds a string plus a separator character.
i.e.
String x = "/usr/";
x.catPostSeparator("bin", '/');
creates "/usr/bin/"
*/
const char *catPostSeparator(const char *value, const char separator);
/**
similiar to above, but puts the separator first
i.e.
String x = "/usr";
x.catPostSeparator('/' "bin");
creates "/usr/bin"
*/
const char *catPreSeparator(const char separator, const char *value);
/**
Inserts the given string value at the beginning of the string. NULL will be
treated as "".
@param value The value to insert.
@ret The new value of the string.
@see cat()
@see catn()
*/
const char *prepend(const char *value);
// replaces string with n chars of val or length of val, whichever is less.
const char *ncpy(const char *newstr, int numchars);
/**
Copies up to maxlen chars from the string into the destination. Differs from
STRNCPY in that it makes sure the destination is always nul-terminated, so
note that maxlen includes the terminating nul.
@param dest The destination to copy to.
@param maxlen How many bytes, at most, to copy.
*/
void strncpyTo(char *dest, int maxlen);
// -----------------------------------------
// Character based find-n-splice methods --
// "l" and "r" prefixes specify to begin at
// front or back of string:
// Returns index of first found, -1 if not found.
int lFindChar(char findval);
int lFindChar(const char *findval); // a list of chars to search for
int rFindChar(char findval);
int rFindChar(const char *findval); // a list of chars to search for
// Splits string at findval. Characters passed by search, including the
// found character, are MOVED to the returned string. If there is no char
// to be found, the entire string is returned and the called instance is
// left empty. (Makes looped splits very easy).
String lSplit(int idxval);
String lSplitChar(char findval);
String lSplitChar(const char *findval);
String rSplit(int idxval);
String rSplitChar(char findval);
String rSplitChar(const char *findval);
// Same as split, except the find char is cut completely.
String lSpliceChar(char findval);
String lSpliceChar(const char *findval);
String rSpliceChar(char findval);
String rSpliceChar(const char *findval);
/**
Replaces all occurences of the value specified by 'find' with the value
specified by 'replace'.
@param find The value to find.
@param replace The value to replace with.
@ret The number of replacements that were executed.
*/
int replace(const char *find, const char *replace);
/**
Replaces fields of same character with 0-padded text representation of an int.
Example: blah$$$$.png becomes blah0000.png
*/
int replaceNumericField(int value, int fieldchar = '\x24');
// UTF8-Aware "Character Based" Methods
/**
Returns how many characters are in the string value. Same as len(), but multibyte UTF-8 aware.
@see len()
@ret Number of logical UTF-8 character in the string.
*/
int numCharacters();
/**
Truncates the length of the string to newlen. If newlen is negative, trims
-newlen characters from the end. Multibyte UTF-8 aware.
@param newlen The new length of the string. If the string is shorter than this, nothing happens. If this value is negative, then the absolute value of newlen is how many characters to trim from the right. I.e. -1 means trim off one character from the end.
@see truncateOnChar()
*/
void trunc(int newlen);
void trim(const char *whitespace = " \t\r\n", int left = true, int right = true);
/**
Does a vsprintf. Used the same way as printf(), but with a va_list instead of "...".
@param format The format string to use.
@param args The argument list in va_list format.
@ret The number of characters in the final string.
*/
int va_sprintf(const char *format, va_list args);
/**
Ensures that the string drops any memory it might have allocated.
*/
void purge();
void swap(String *); // swaps buffers with another string
void swap(String &); // swaps buffers with another string
void own(char *); // take ownership of a buffer
void AppendPath(const char *path);
protected:
char * val;
enum { wastage_allowed = 128 };
};
/**
String class with a printf-style constructor. Otherwise identical to String.
Also takes some standard types, like int, double, and GUID.
@see GUID
@see String
*/
class StringPrintf : public String
{
public:
StringPrintf(const char *format = NULL, ...);
StringPrintf(int value);
StringPrintf(double value);
StringPrintf(GUID g);
};
class StringToLower : public String
{
public:
StringToLower(const char *val = NULL) : String(val)
{
tolower();
}
};
class StringToUpper : public String
{
public:
StringToUpper(const char *val = NULL) : String(val)
{
toupper();
}
};
#if defined(NDEBUG) && defined(WASABI_NO_RELEASEMODE_DEBUGSTRINGS)
#define DebugString __noop
#else
#define DebugString _DebugString
#endif
class _DebugString : public String
{
public:
_DebugString(const char *format = NULL, ...);
_DebugString(const String &s);
_DebugString(const String *s);
void debugPrint();
};
#define RecycleString String
// String operators using StringPrintf
inline const char *String::operator +=(char value)
{
return cat(StringPrintf("%c", value)); // Uhm. Shouldn't the string be given
// the "Fast" methods and the Printf be
// built off of that?
}
inline const char *String::operator +=(int value)
{
return cat(StringPrintf("%i", value));
}
inline const char *String::operator +=(GUID guid)
{
return cat(StringPrintf(guid));
}
//
// Global operator overrides to allow string to take over for
// the use of standard operators with const char pointers as
// left hand operands.
inline int operator ==(const char *v1, const String &v2)
{
return v2.isequal(v1);
}
inline int operator !=(const char *v1, const String &v2)
{
return !v2.isequal(v1);
}
inline int operator <(const char *v1, const String &v2)
{
return !v2.islessthan(v1);
}
inline int operator >(const char *v1, const String &v2)
{
return v2.islessthan(v1);
}
/**
Compares two strings. Generally used with PtrListSorted<>
@see PtrListSorted
*/
class StringComparator
{
public:
// comparator for sorting
static int compareItem(String *p1, String* p2);
// comparator for searching
static int compareAttrib(const wchar_t *attrib, String *item);
};
#endif // __cplusplus
#endif

View File

@ -0,0 +1,95 @@
#include "precomp_wasabi_bfc.h"
#include "bigstring.h"
BigString::BigString() {
mem = NULL;
m_linecount = 0;
}
BigString::~BigString() {
if (mem != NULL) {
FREE(mem);
}
strings.deleteAll();
}
const char *BigString::getValue() /*const*/ {
if (mem != NULL) return mem;
size_t l = 0;
foreach(strings)
l += strings.getfor()->len();
endfor;
mem = (char *)MALLOC(l+1);
char *p = mem;
String *s = NULL;
size_t sl = 0;
foreach(strings)
s = strings.getfor();
sl = s->len();
if (sl > 0) MEMCPY((void *)p, (void *)s->getValue(), sl);
p += sl;
endfor;
*p = 0;
return mem;
}
void BigString::setValue(const char *val) {
if (mem != NULL) {
FREE(mem);
mem = NULL;
}
strings.deleteAll();
cat(val);
}
int BigString::isempty() {
if (strings.getNumItems() == 0) return 1;
foreach(strings)
if (!strings.getfor()->isempty()) return 0;
endfor;
return 1;
}
void BigString::reset() {
if (mem != NULL) {
FREE(mem);
mem = NULL;
}
strings.deleteAll();
m_linecount = 0;
}
void BigString::catn(const char *s, int n) {
String *str = new String();
str->catn(s, n);
cat(str->getValue());
}
void BigString::cat(const char *s) {
if (mem != NULL) {
FREE(mem);
mem = NULL;
}
char *p = (char *)s;
while (p && *p) {
if (*p == '\r' || *p == '\n') {
if (*(p+1) == '\n' && *p == '\r') p++;
m_linecount++;
}
p++;
}
strings.addItem(new String(s));
}
char BigString::lastChar() {
return strings.getLast()->lastChar();
}
char BigString::firstChar() {
const char *s = strings.getFirst()->getValue();
return s ? *s : 0;
}
int BigString::getLineCount() {
return m_linecount;
}

View File

@ -0,0 +1,56 @@
#ifndef __BIGSTRING_H
#define __BIGSTRING_H
/*
A class tor concatenate chunks of texts into one big pool. This is much faster than using String if you are adding
a lot of tiny pieces into one giant block (a typical cases of this is when writing xml). Upon request for the value,
the class allocates one big block of memory and copies all the strings into it serially (as opposed to String
reallocating the entire block at each concatenation). Note that because of the type of implementation BigString has
to use, you cannot get the full block as a return value to your concatenations and assignments (+= and = return void).
To do this, request the value explicitely (this should be kept to a strict minimum or the advantage of BigString over
String will disapear)
*/
#include <bfc/string/bfcstring.h>
#include <bfc/ptrlist.h>
class BigString {
public:
BigString();
virtual ~BigString();
operator const char *() /*const*/ { return getValue(); }
const char *getValue() /*const*/;
char *getNonConstVal() { return (char *)getValue(); }
void setValue(const char *val);
// copy assignment operator
BigString& operator =(/*const*/ BigString &s) {
if (this != &s)
setValue(s);
return *this;
}
void operator =(const char *newval) { setValue(newval); }
void operator +=(const char *addval) {
cat(addval);
}
int isempty();
void reset();
void catn(const char *s, int n);
void cat(const char *s);
char lastChar();
char firstChar();
int getLineCount();
private:
PtrList<String> strings;
char *mem;
int m_linecount;
};
#endif

View File

@ -0,0 +1,156 @@
#include "precomp_wasabi_bfc.h"
// someday, there will be a file here.
#include <bfc/wasabi_std.h>
#include "encodedstr.h"
#include <bfc/string/bfcstring.h>
#include <api/service/svcs/svc_stringconverter.h>
#include <api/memmgr/api_memmgr.h>
EncodedStr::EncodedStr(FOURCC encodingType, void *encodedBuffer, int bufferSize, int deleteIt) {
encoding_type = encodingType;
encoded_buffer = encodedBuffer;
buffer_size = bufferSize;
delete_it = deleteIt;
}
EncodedStr::~EncodedStr() {
if (delete_it && (encoded_buffer != NULL)) {
#ifdef WASABI_COMPILE_MEMMGR
WASABI_API_MEMMGR->sysFree(encoded_buffer);
#else
free(encoded_buffer);
#endif
}
}
void EncodedStr::resetBuffer(FOURCC encodingType, void *encodedBuffer, int bufferSize, int deleteIt) {
// if there's someone already there, toss them.
if (delete_it && (encoded_buffer != NULL)) {
#ifdef WASABI_COMPILE_MEMMGR
WASABI_API_MEMMGR->sysFree(encoded_buffer);
#else
free(encoded_buffer);
#endif
}
encoding_type = encodingType;
encoded_buffer = encodedBuffer;
buffer_size = bufferSize;
delete_it = deleteIt;
}
int EncodedStr::convertToUTF8(String &output_str) {
int retval = 0;
StringConverterEnum myServiceEnum(encoding_type);
svc_stringConverter *myConv = myServiceEnum.getFirst();
if (myConv != NULL) {
void *in_buffer = encoded_buffer;
int size_in_bytes = buffer_size;
if (encoded_buffer != NULL) {
// Preflight
int u8size = myConv->preflightToUTF8(encoding_type, in_buffer, size_in_bytes);
// Alloc
#ifdef WASABI_COMPILE_MEMMGR
char *u8str = reinterpret_cast<char *>(WASABI_API_MEMMGR->sysMalloc(u8size));
#else
char *u8str = reinterpret_cast<char *>(MALLOC(u8size));
#endif
if (u8str != NULL) {
// Convert
retval = myConv->convertToUTF8(encoding_type, in_buffer, size_in_bytes, u8str, u8size);
if (retval < 0) {
// Clear on error.
#ifdef WASABI_COMPILE_MEMMGR
WASABI_API_MEMMGR->sysFree(u8str);
#else
free(encoded_buffer);
#endif
u8str = NULL;
}
} else {
ASSERTPR(u8str != NULL, "Malloc failed in string converter\n");
}
// And call the method to inject the pointer into our string (cleared on error).
output_str.setValue(u8str);
}
// Once we use our service, release our locked instance of it.
myServiceEnum.release(myConv);
} else {
// Clear the string on error.
retval = SvcStrCnv::ERROR_UNAVAILABLE;
output_str.setValue(NULL);
}
return retval;
}
int EncodedStr::convertFromUTF8(FOURCC encodingType, const String &inputStr) {
int retval = 0;
int written = 0;
void *buffer = NULL;
StringConverterEnum myServiceEnum(encodingType);
svc_stringConverter *myConv = myServiceEnum.getFirst();
if (myConv != NULL) {
if (inputStr != NULL) {
const char *val = inputStr.getValue();
int valsize = STRLEN(val) + 1; // count the null char in your size-in-bytes!
// Preflight
int size = myConv->preflightFromUTF8(encodingType, val, valsize);
if (size > 0) {
// Alloc
#ifdef WASABI_COMPILE_MEMMGR
buffer = WASABI_API_MEMMGR->sysMalloc(size);
#else
buffer = MALLOC(size);
#endif
if (buffer != NULL) {
// Convert
written = myConv->convertFromUTF8(encodingType, val, valsize, buffer, size);
if (written > 0) {
retval = written;
} else {
// Clear on error.
#ifdef WASABI_COMPILE_MEMMGR
WASABI_API_MEMMGR->sysFree(buffer);
#else
free(buffer);
#endif
buffer = NULL;
retval = written;
written = 0;
}
} else {
ASSERTPR(buffer != NULL, "Malloc failed in string converter\n");
}
} else {
// Clear on error.
buffer = NULL;
retval = size;
written = 0;
}
}
// Once we use our service, release our locked instance of it.
myServiceEnum.release(myConv);
} else {
// On error locking down a service, all the default values are errors and called through resetBuffer.
retval = SvcStrCnv::ERROR_UNAVAILABLE;
}
resetBuffer(encodingType, buffer, written);
return retval;
}
// This is for debugging.
int EncodedStr::operator ==(const EncodedStr &in_string) {
if (encoding_type == in_string.encoding_type) {
switch (encoding_type) {
case SvcStrCnv::OSNATIVE:
return (STRCMP(reinterpret_cast<char *>(encoded_buffer), reinterpret_cast<char *>(in_string.encoded_buffer)) == 0);
break;
default:
return 0;
break;
}
}
return 0;
}

View File

@ -0,0 +1,42 @@
#ifndef _ENCODEDSTR_H
#define _ENCODEDSTR_H
#include <api/service/svcs/svc_stringtypes.h>
class String;
class EncodedStr {
public:
// The EncodedStr object will automatically delete its ram, unless you
// specify 0 in that "delete it" parameter there, partner.
EncodedStr(FOURCC encodingType = 0, void *encodedBuffer = NULL, int bufferSize = 0, int deleteIt = 1);
~EncodedStr();
// A "reset" will ensure any previously set buffer will be deleted
void resetBuffer(FOURCC encodingType, void *encodedBuffer, int bufferSize, int deleteIt = 1);
// All the calls to the service level functions are through here.
int convertToUTF8(String &output_str);
// This method will reset this object (ie: delete RAM if necessary)
int convertFromUTF8(FOURCC encodingType, const String &inputStr);
// Accessor inlines
inline FOURCC getEncodingType() { return encoding_type; }
inline void *getEncodedBuffer() { return encoded_buffer; }
inline int getBufferSize() { return buffer_size; }
inline int getDeleteIt() { return delete_it; }
// This is for debugging.
int operator ==(const EncodedStr &in_string);
private:
FOURCC encoding_type;
void * encoded_buffer;
int buffer_size;
int delete_it;
};
#endif//_ENCODEDSTR_H

Some files were not shown because too many files have changed in this diff Show More