aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/bfc/platform
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/bfc/platform')
-rw-r--r--Src/Wasabi/bfc/platform/Makefile.am6
-rw-r--r--Src/Wasabi/bfc/platform/Makefile.in376
-rw-r--r--Src/Wasabi/bfc/platform/export.h20
-rw-r--r--Src/Wasabi/bfc/platform/guid.h1
-rw-r--r--Src/Wasabi/bfc/platform/linux.h437
-rw-r--r--Src/Wasabi/bfc/platform/linux/linux.cpp961
-rw-r--r--Src/Wasabi/bfc/platform/minmax.h19
-rw-r--r--Src/Wasabi/bfc/platform/platform.cpp6
-rw-r--r--Src/Wasabi/bfc/platform/platform.h498
-rw-r--r--Src/Wasabi/bfc/platform/std_string_osx.cpp246
-rw-r--r--Src/Wasabi/bfc/platform/strcmp.h15
-rw-r--r--Src/Wasabi/bfc/platform/types.h2
-rw-r--r--Src/Wasabi/bfc/platform/win32.h34
13 files changed, 2621 insertions, 0 deletions
diff --git a/Src/Wasabi/bfc/platform/Makefile.am b/Src/Wasabi/bfc/platform/Makefile.am
new file mode 100644
index 00000000..aa27d337
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/Makefile.am
@@ -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
diff --git a/Src/Wasabi/bfc/platform/Makefile.in b/Src/Wasabi/bfc/platform/Makefile.in
new file mode 100644
index 00000000..3ccf8a57
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/Makefile.in
@@ -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:
diff --git a/Src/Wasabi/bfc/platform/export.h b/Src/Wasabi/bfc/platform/export.h
new file mode 100644
index 00000000..68e6e3c9
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/export.h
@@ -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 \ No newline at end of file
diff --git a/Src/Wasabi/bfc/platform/guid.h b/Src/Wasabi/bfc/platform/guid.h
new file mode 100644
index 00000000..3724f6e1
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/guid.h
@@ -0,0 +1 @@
+#include "../../../replicant/foundation/guid.h"
diff --git a/Src/Wasabi/bfc/platform/linux.h b/Src/Wasabi/bfc/platform/linux.h
new file mode 100644
index 00000000..b57ec3f0
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/linux.h
@@ -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
+
diff --git a/Src/Wasabi/bfc/platform/linux/linux.cpp b/Src/Wasabi/bfc/platform/linux/linux.cpp
new file mode 100644
index 00000000..67471d4a
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/linux/linux.cpp
@@ -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
diff --git a/Src/Wasabi/bfc/platform/minmax.h b/Src/Wasabi/bfc/platform/minmax.h
new file mode 100644
index 00000000..ccc37e96
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/minmax.h
@@ -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 \ No newline at end of file
diff --git a/Src/Wasabi/bfc/platform/platform.cpp b/Src/Wasabi/bfc/platform/platform.cpp
new file mode 100644
index 00000000..bd9ece7b
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/platform.cpp
@@ -0,0 +1,6 @@
+#include "precomp_wasabi_bfc.h"
+#include "platform.h"
+
+void link_platform() {
+ OutputDebugString(L"dummy");
+} \ No newline at end of file
diff --git a/Src/Wasabi/bfc/platform/platform.h b/Src/Wasabi/bfc/platform/platform.h
new file mode 100644
index 00000000..6a14967a
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/platform.h
@@ -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
+
diff --git a/Src/Wasabi/bfc/platform/std_string_osx.cpp b/Src/Wasabi/bfc/platform/std_string_osx.cpp
new file mode 100644
index 00000000..ecfb16db
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/std_string_osx.cpp
@@ -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);
+}
diff --git a/Src/Wasabi/bfc/platform/strcmp.h b/Src/Wasabi/bfc/platform/strcmp.h
new file mode 100644
index 00000000..f76d47af
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/strcmp.h
@@ -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 \ No newline at end of file
diff --git a/Src/Wasabi/bfc/platform/types.h b/Src/Wasabi/bfc/platform/types.h
new file mode 100644
index 00000000..ff83ce04
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/types.h
@@ -0,0 +1,2 @@
+#include <bfc/platform/platform.h>
+#include "../replicant/foundation/types.h" \ No newline at end of file
diff --git a/Src/Wasabi/bfc/platform/win32.h b/Src/Wasabi/bfc/platform/win32.h
new file mode 100644
index 00000000..73d8872e
--- /dev/null
+++ b/Src/Wasabi/bfc/platform/win32.h
@@ -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;
+