summaryrefslogtreecommitdiff
path: root/gfx/gdi
diff options
context:
space:
mode:
authorGraeme Geldenhuys <graemeg@users.sourceforge.net>2006-11-18 18:11:20 +0000
committerGraeme Geldenhuys <graemeg@users.sourceforge.net>2006-11-18 18:11:20 +0000
commit8fe7ea95a343a35dc286bd9a13d257d285e9c4e1 (patch)
treeea9f9317f46f4c320a2667e0e0d4362c4f0980a3 /gfx/gdi
parent546dce65494ea4e5f654e2840cc67307101e06f7 (diff)
downloadfpGUI-8fe7ea95a343a35dc286bd9a13d257d285e9c4e1.tar.xz
Initial checkin. Merged fpGUI, fpGFX and fpIMG from the OpenSoft sever.
Diffstat (limited to 'gfx/gdi')
-rw-r--r--gfx/gdi/Makefile1249
-rw-r--r--gfx/gdi/Makefile.fpc36
-rw-r--r--gfx/gdi/fpgfxpackage.lpk68
-rw-r--r--gfx/gdi/fpgfxpackage.pas14
-rw-r--r--gfx/gdi/gdikeys.inc330
-rw-r--r--gfx/gdi/gfx_gdi.pas1730
-rw-r--r--gfx/gdi/gfxinterface.pas39
7 files changed, 3466 insertions, 0 deletions
diff --git a/gfx/gdi/Makefile b/gfx/gdi/Makefile
new file mode 100644
index 00000000..753cac82
--- /dev/null
+++ b/gfx/gdi/Makefile
@@ -0,0 +1,1249 @@
+#
+# Makefile generated by fpcmake v1.00 [2000/12/14]
+#
+
+defaultrule: all
+
+#####################################################################
+# Autodetect OS (Linux or Dos or Windows NT)
+# define inUnix when running under Unix (Linux,FreeBSD)
+# define inWinNT when running under WinNT
+#####################################################################
+
+# We need only / in the path
+override PATH:=$(subst \,/,$(PATH))
+
+# Search for PWD and determine also if we are under linux
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(subst ;, ,$(PATH)))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(subst :, ,$(PATH)))))
+ifeq ($(PWD),)
+nopwd:
+ @echo You need the GNU utils package to use this Makefile!
+ @echo Get ftp://ftp.freepascal.org/pub/fpc/dist/go32v2/utilgo32.zip
+ @exit
+else
+inUnix=1
+endif
+else
+PWD:=$(firstword $(PWD))
+endif
+
+# Detect NT - NT sets OS to Windows_NT
+# Detect OS/2 - OS/2 has OS2_SHELL defined
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+endif
+
+# The extension of executables
+ifdef inUnix
+SRCEXEEXT=
+else
+SRCEXEEXT=.exe
+endif
+
+# The path which is searched separated by spaces
+ifdef inUnix
+SEARCHPATH=$(subst :, ,$(PATH))
+else
+SEARCHPATH=$(subst ;, ,$(PATH))
+endif
+
+# Base dir
+ifdef PWD
+BASEDIR:=$(shell $(PWD))
+else
+BASEDIR=.
+endif
+
+#####################################################################
+# FPC version/target Detection
+#####################################################################
+
+# What compiler to use ?
+ifndef FPC
+# Compatibility with old makefiles
+ifdef PP
+FPC=$(PP)
+else
+FPC=ppc386
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+
+# Target OS
+ifndef OS_TARGET
+OS_TARGET:=$(shell $(FPC) -iTO)
+endif
+
+# Source OS
+ifndef OS_SOURCE
+OS_SOURCE:=$(shell $(FPC) -iSO)
+endif
+
+# Target CPU
+ifndef CPU_TARGET
+CPU_TARGET:=$(shell $(FPC) -iTP)
+endif
+
+# Source CPU
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(shell $(FPC) -iSP)
+endif
+
+# FPC version
+ifndef FPC_VERSION
+FPC_VERSION:=$(shell $(FPC) -iV)
+endif
+
+export FPC OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FPC_VERSION FPCOPT
+
+#####################################################################
+# FPCDIR Setting
+#####################################################################
+
+# Test FPCDIR to look if the RTL dir exists
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(FPCDIR)/rtl),)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=wrong
+endif
+endif
+else
+override FPCDIR=wrong
+endif
+
+# Default FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR=../../../..
+ifeq ($(wildcard $(FPCDIR)/rtl),)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=wrong
+endif
+endif
+endif
+
+# Detect FPCDIR
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(FPCDIR)/rtl),)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(FPCDIR)/rtl),)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+endif
+
+ifndef PACKAGESDIR
+PACKAGESDIR=$(FPCDIR)/packages
+endif
+ifndef TOOLKITSDIR
+TOOLKITSDIR=
+endif
+ifndef COMPONENTSDIR
+COMPONENTSDIR=
+endif
+
+# Create units dir
+ifneq ($(FPCDIR),.)
+UNITSDIR=$(FPCDIR)/units/$(OS_TARGET)
+endif
+
+#####################################################################
+# User Settings
+#####################################################################
+
+
+# Targets
+
+override UNITOBJECTS+=gfx_gdi gfximpl
+override RSTOBJECTS+=gfx_gdi
+
+# Clean
+
+
+# Install
+
+ZIPTARGET=install
+
+# Defaults
+
+override NEEDOPT=-S2ht
+
+# Directories
+
+override NEEDUNITDIR=..
+
+# Packages
+
+override PACKAGES+=rtl
+
+# Libraries
+
+LIBNAME=fpgfx_gdi
+
+# Info
+
+INFOTARGET=fpc_infocfg fpc_infoobjects fpc_infoinstall
+
+#####################################################################
+# Shell tools
+#####################################################################
+
+# echo
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(EXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=echo
+ECHOE:=echo
+else
+ECHO:=$(firstword $(ECHO))
+ECHOE=$(ECHO) -E
+endif
+else
+ECHO:=$(firstword $(ECHO))
+ECHOE=$(ECHO) -E
+endif
+endif
+
+# To copy pograms
+ifndef COPY
+COPY:=cp -fp
+endif
+
+# Copy a whole tree
+ifndef COPYTREE
+COPYTREE:=cp -rfp
+endif
+
+# To move pograms
+ifndef MOVE
+MOVE:=mv -f
+endif
+
+# Check delete program
+ifndef DEL
+DEL:=rm -f
+endif
+
+# Check deltree program
+ifndef DELTREE
+DELTREE:=rm -rf
+endif
+
+# To install files
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=install -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+
+# To install programs
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=install -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+
+# To make a directory.
+ifndef MKDIR
+ifdef inUnix
+MKDIR:=install -m 755 -d
+else
+MKDIR:=ginstall -m 755 -d
+endif
+endif
+
+export ECHO ECHOE COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+
+#####################################################################
+# Default Tools
+#####################################################################
+
+# assembler, redefine it if cross compiling
+ifndef AS
+AS=as
+endif
+
+# linker, but probably not used
+ifndef LD
+LD=ld
+endif
+
+# ppas.bat / ppas.sh
+ifdef inUnix
+PPAS=ppas.sh
+else
+ifdef inOS2
+PPAS=ppas.cmd
+else
+PPAS=ppas.bat
+endif
+endif
+
+# ldconfig to rebuild .so cache
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+
+# ppumove
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE=
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+
+# ppufiles
+ifndef PPUFILES
+PPUFILES:=$(strip $(wildcard $(addsuffix /ppufiles$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUFILES),)
+PPUFILES=
+else
+PPUFILES:=$(firstword $(PPUFILES))
+endif
+endif
+export PPUFILES
+
+# Look if UPX is found for go32v2 and win32. We can't use $UPX becuase
+# upx uses that one itself (PFV)
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+
+# ZipProg, you can't use Zip as the var name (PFV)
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG=
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+
+ZIPOPT=-9
+ZIPEXT=.zip
+
+# Tar
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG=
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+
+ifeq ($(USETAR),bz2)
+TAROPT=vI
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+
+#####################################################################
+# Default extensions
+#####################################################################
+
+# Default needed extensions (Go32v2,Linux)
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+RSTEXT=.rst
+FPCMADE=fpcmade
+
+# Go32v1
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+FPCMADE=fpcmade.v1
+endif
+
+# Go32v2
+ifeq ($(OS_TARGET),go32v2)
+FPCMADE=fpcmade.dos
+endif
+
+# Linux
+ifeq ($(OS_TARGET),linux)
+EXEEXT=
+HASSHAREDLIB=1
+FPCMADE=fpcmade.lnx
+endif
+
+# Linux
+ifeq ($(OS_TARGET),freebsd)
+EXEEXT=
+HASSHAREDLIB=1
+FPCMADE=fpcmade.freebsd
+endif
+
+# Win32
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+FPCMADE=fpcmade.w32
+endif
+
+# OS/2
+ifeq ($(OS_TARGET),os2)
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+SMARTEXT=.so
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+FPCMADE=fpcmade.os2
+endif
+
+# library prefix
+LIBPREFIX=lib
+ifeq ($(OS_TARGET),go32v2)
+LIBPREFIX=
+endif
+ifeq ($(OS_TARGET),go32v1)
+LIBPREFIX=
+endif
+
+# determine which .pas extension is used
+ifndef PASEXT
+ifdef EXEOBJECTS
+override TESTPAS:=$(strip $(wildcard $(addsuffix .pas,$(firstword $(EXEOBJECTS)))))
+else
+override TESTPAS:=$(strip $(wildcard $(addsuffix .pas,$(firstword $(UNITOBJECTS)))))
+endif
+ifeq ($(TESTPAS),)
+PASEXT=.pp
+else
+PASEXT=.pas
+endif
+endif
+
+
+# Check if the dirs really exists, else turn it off
+ifeq ($(wildcard $(UNITSDIR)),)
+UNITSDIR=
+endif
+ifeq ($(wildcard $(TOOLKITSDIR)),)
+TOOLKITSDIR=
+endif
+ifeq ($(wildcard $(PACKAGESDIR)),)
+PACKAGESDIR=
+endif
+ifeq ($(wildcard $(COMPONENTSDIR)),)
+COMPONENTSDIR=
+endif
+
+
+# PACKAGESDIR packages
+
+PACKAGERTL=1
+
+ifdef PACKAGERTL
+ifneq ($(wildcard $(FPCDIR)/rtl),)
+ifneq ($(wildcard $(FPCDIR)/rtl/$(OS_TARGET)),)
+PACKAGEDIR_RTL=$(FPCDIR)/rtl/$(OS_TARGET)
+else
+PACKAGEDIR_RTL=$(FPCDIR)/rtl
+endif
+ifeq ($(wildcard $(PACKAGEDIR_RTL)/$(FPCMADE)),)
+override COMPILEPACKAGES+=package_rtl
+package_rtl:
+ $(MAKE) -C $(PACKAGEDIR_RTL) all
+endif
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+else
+PACKAGEDIR_RTL=
+ifneq ($(wildcard $(UNITSDIR)/rtl),)
+ifneq ($(wildcard $(UNITSDIR)/rtl/$(OS_TARGET)),)
+UNITDIR_RTL=$(UNITSDIR)/rtl/$(OS_TARGET)
+else
+UNITDIR_RTL=$(UNITSDIR)/rtl
+endif
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override NEEDUNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+
+
+#####################################################################
+# Default Directories
+#####################################################################
+
+# Linux and freebsd use unix dirs with /usr/bin, /usr/lib
+# When zipping use the target as default, when normal install then
+# use the source os as default
+ifdef ZIPNAME
+# Zipinstall
+ifeq ($(OS_TARGET),linux)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_TARGET),freebsd)
+UNIXINSTALLDIR=1
+endif
+else
+# Normal install
+ifeq ($(OS_SOURCE),linux)
+UNIXINSTALLDIR=1
+endif
+ifeq ($(OS_SOURCE),freebsd)
+UNIXINSTALLDIR=1
+endif
+endif
+
+# set the prefix directory where to install everything
+ifndef PREFIXINSTALLDIR
+ifdef UNIXINSTALLDIR
+PREFIXINSTALLDIR=/usr
+else
+PREFIXINSTALLDIR=/pp
+endif
+endif
+export PREFIXINSTALLDIR
+
+# Where to place the resulting zip files
+ifndef DESTZIPDIR
+DESTZIPDIR:=$(BASEDIR)
+endif
+export DESTZIPDIR
+
+#####################################################################
+# Install Directories
+#####################################################################
+
+# set the base directory where to install everything
+ifndef BASEINSTALLDIR
+ifdef UNIXINSTALLDIR
+BASEINSTALLDIR=$(PREFIXINSTALLDIR)/lib/fpc/$(FPC_VERSION)
+else
+BASEINSTALLDIR=$(PREFIXINSTALLDIR)
+endif
+endif
+
+# set the directory where to install the binaries
+ifndef BININSTALLDIR
+ifdef UNIXINSTALLDIR
+BININSTALLDIR=$(PREFIXINSTALLDIR)/bin
+else
+BININSTALLDIR=$(BASEINSTALLDIR)/bin/$(OS_TARGET)
+endif
+endif
+
+# set the directory where to install the units.
+ifndef UNITINSTALLDIR
+UNITINSTALLDIR=$(BASEINSTALLDIR)/units/$(OS_TARGET)
+ifdef UNITSUBDIR
+UNITINSTALLDIR:=$(UNITINSTALLDIR)/$(UNITSUBDIR)
+endif
+endif
+
+# Where to install shared libraries
+ifndef LIBINSTALLDIR
+ifdef UNIXINSTALLDIR
+LIBINSTALLDIR=$(PREFIXINSTALLDIR)/lib
+else
+LIBINSTALLDIR=$(UNITINSTALLDIR)
+endif
+endif
+
+# Where the source files will be stored
+ifndef SOURCEINSTALLDIR
+ifdef UNIXINSTALLDIR
+SOURCEINSTALLDIR=$(PREFIXINSTALLDIR)/src/fpc-$(FPC_VERSION)
+else
+SOURCEINSTALLDIR=$(BASEINSTALLDIR)/source
+endif
+ifdef SOURCESUBDIR
+SOURCEINSTALLDIR:=$(SOURCEINSTALLDIR)/$(SOURCESUBDIR)
+endif
+endif
+
+# Where the doc files will be stored
+ifndef DOCINSTALLDIR
+ifdef UNIXINSTALLDIR
+DOCINSTALLDIR=$(PREFIXINSTALLDIR)/doc/fpc-$(FPC_VERSION)
+else
+DOCINSTALLDIR=$(BASEINSTALLDIR)/doc
+endif
+endif
+
+# Where to install the examples, under linux we use the doc dir
+# because the copytree command will create a subdir itself
+ifndef EXAMPLEINSTALLDIR
+ifdef UNIXINSTALLDIR
+EXAMPLEINSTALLDIR=$(DOCINSTALLDIR)/examples
+else
+EXAMPLEINSTALLDIR=$(BASEINSTALLDIR)/examples
+endif
+ifdef EXAMPLESUBDIR
+EXAMPLEINSTALLDIR:=$(EXAMPLEINSTALLDIR)/$(EXAMPLESUBDIR)
+endif
+endif
+
+# Where the some extra (data)files will be stored
+ifndef DATAINSTALLDIR
+DATAINSTALLDIR=$(BASEINSTALLDIR)
+endif
+
+#####################################################################
+# Redirection
+#####################################################################
+
+ifndef REDIRFILE
+REDIRFILE=log
+endif
+
+ifdef REDIR
+ifndef inUnix
+override FPC=redir -eo $(FPC)
+endif
+# set the verbosity to max
+override FPCOPT+=-va
+override REDIR:= >> $(REDIRFILE)
+endif
+
+
+#####################################################################
+# Compiler Command Line
+#####################################################################
+
+# Load commandline OPTDEF and add FPC_CPU define
+override FPCOPTDEF:=-d$(CPU_TARGET)
+
+# Load commandline OPT and add target and unit dir to be sure
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+
+# User dirs should be first, so they are looked at first
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+
+# Smartlinking
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+
+# Smartlinking creation
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+
+# Debug
+ifdef DEBUG
+override FPCOPT+=-gl -dDEBUG
+endif
+
+# Release mode (strip, optimize and don't load ppc386.cfg)
+# 0.99.12b has a bug in the optimizer so don't use it by default
+ifdef RELEASE
+ifeq ($(FPC_VERSION),0.99.12)
+override FPCOPT+=-Xs -OGp3 -n
+else
+override FPCOPT+=-Xs -OG2p3 -n
+endif
+endif
+
+# Strip
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+
+# Optimizer
+ifdef OPTIMIZE
+override FPCOPT+=-OG2p3
+endif
+
+# Verbose settings (warning,note,info)
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+
+ifdef NEEDOPT
+override FPCOPT+=$(NEEDOPT)
+endif
+
+ifdef NEEDUNITDIR
+override FPCOPT+=$(addprefix -Fu,$(NEEDUNITDIR))
+endif
+
+ifdef UNITSDIR
+override FPCOPT+=-Fu$(UNITSDIR)
+endif
+
+# Target dirs and the prefix to use for clean/install
+ifdef TARGETDIR
+override FPCOPT+=-FE$(TARGETDIR)
+ifeq ($(TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(TARGETDIR)/
+endif
+endif
+ifdef UNITTARGETDIR
+override FPCOPT+=-FU$(UNITTARGETDIR)
+ifeq ($(UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(TARGETDIR)/
+endif
+else
+ifdef TARGETDIR
+override UNITTARGETDIR=$(TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+
+# Add commandline options last so they can override
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+
+# Add defines from FPCOPTDEF to FPCOPT
+ifdef FPCOPTDEF
+override FPCOPT+=$(FPCOPTDEF)
+endif
+
+# Error file ?
+ifdef ERRORFILE
+override FPCOPT+=-Fr$(ERRORFILE)
+endif
+
+# Was a config file specified ?
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+
+# For win32 the options are passed using the environment FPCEXTCMD
+ifeq ($(OS_SOURCE),win32)
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+
+# Compiler commandline
+override COMPILER:=$(FPC) $(FPCOPT)
+
+# also call ppas if with command option -s
+# but only if the OS_SOURCE and OS_TARGE are equal
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+
+#####################################################################
+# Standard rules
+#####################################################################
+
+all: fpc_all
+
+debug: fpc_debug
+
+smart: fpc_smart
+
+shared: fpc_shared
+
+showinstall: fpc_showinstall
+
+install: fpc_install
+
+sourceinstall: fpc_sourceinstall
+
+exampleinstall: fpc_exampleinstall
+
+zipinstall: fpc_zipinstall
+
+zipsourceinstall: fpc_zipsourceinstall
+
+zipexampleinstall: fpc_zipexampleinstall
+
+clean: fpc_clean
+
+distclean: fpc_distclean
+
+cleanall: fpc_cleanall
+
+info: fpc_info
+
+.PHONY: all debug smart shared showinstall install sourceinstall exampleinstall zipinstall zipsourceinstall zipexampleinstall clean distclean cleanall info
+
+#####################################################################
+# Units
+#####################################################################
+
+.PHONY: fpc_units
+
+override ALLTARGET+=fpc_units
+
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(UNITOBJECTS))
+override INSTALLPPUFILES+=$(UNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES)
+
+fpc_units: $(UNITPPUFILES)
+
+#####################################################################
+# Resource strings
+#####################################################################
+
+ifdef RSTOBJECTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(RSTOBJECTS))
+
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+
+#####################################################################
+# General compile rules
+#####################################################################
+
+.PHONY: fpc_packages fpc_all fpc_debug
+
+$(FPCMADE): $(ALLTARGET)
+ @$(ECHO) Compiled > $(FPCMADE)
+
+fpc_packages: $(COMPILEPACKAGES)
+
+fpc_all: fpc_packages $(FPCMADE)
+
+fpc_debug:
+ $(MAKE) all DEBUG=1
+
+# Search paths for .ppu if targetdir is set
+ifdef UNITTARGETDIR
+vpath %$(PPUEXT) $(UNITTARGETDIR)
+endif
+
+# General compile rules, available for both possible PASEXT
+
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .pp
+
+%$(PPUEXT): %.pp
+ $(COMPILER) $< $(REDIR)
+ $(EXECPPAS)
+
+%$(PPUEXT): %.pas
+ $(COMPILER) $< $(REDIR)
+ $(EXECPPAS)
+
+%$(EXEEXT): %.pp
+ $(COMPILER) $< $(REDIR)
+ $(EXECPPAS)
+
+%$(EXEEXT): %.pas
+ $(COMPILER) $< $(REDIR)
+ $(EXECPPAS)
+
+#####################################################################
+# Library
+#####################################################################
+
+.PHONY: fpc_smart fpc_shared
+
+ifdef LIBVERSION
+LIBFULLNAME=$(LIBNAME).$(LIBVERSION)
+else
+LIBFULLNAME=$(LIBNAME)
+endif
+
+# Default sharedlib units are all unit objects
+ifndef SHAREDLIBUNITOBJECTS
+SHAREDLIBUNITOBJECTS:=$(UNITOBJECTS)
+endif
+
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+
+fpc_shared: all
+ifdef HASSHAREDLIB
+ifndef LIBNAME
+ @$(ECHO) "LIBNAME not set"
+else
+ $(PPUMOVE) $(SHAREDLIBUNITOBJECTS) -o$(LIBFULLNAME)
+endif
+else
+ @$(ECHO) "Shared Libraries not supported"
+endif
+
+#####################################################################
+# Install rules
+#####################################################################
+
+.PHONY: fpc_showinstall fpc_install
+
+ifdef EXTRAINSTALLUNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(EXTRAINSTALLUNITS))
+endif
+
+ifdef INSTALLPPUFILES
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(INSTALLPPUFILES))
+ifdef PPUFILES
+INSTALLPPULINKFILES:=$(shell $(PPUFILES) -S -O $(INSTALLPPUFILES))
+else
+INSTALLPPULINKFILES:=$(wildcard $(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(LIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))))
+endif
+override INSTALLPPULINKFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(INSTALLPPULINKFILES))
+endif
+
+ifdef INSTALLEXEFILES
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(INSTALLEXEFILES))
+endif
+
+fpc_showinstall: $(SHOWINSTALLTARGET)
+ifdef INSTALLEXEFILES
+ @$(ECHO) -e $(addprefix "\n"$(BININSTALLDIR)/,$(INSTALLEXEFILES))
+endif
+ifdef INSTALLPPUFILES
+ @$(ECHO) -e $(addprefix "\n"$(UNITINSTALLDIR)/,$(INSTALLPPUFILES))
+ifneq ($(INSTALLPPULINKFILES),)
+ @$(ECHO) -e $(addprefix "\n"$(UNITINSTALLDIR)/,$(INSTALLPPULINKFILES))
+endif
+ifneq ($(wildcard $(LIBFULLNAME)),)
+ @$(ECHO) $(LIBINSTALLDIR)/$(LIBFULLNAME)
+ifdef HASSHAREDLIB
+ @$(ECHO) $(LIBINSTALLDIR)/$(LIBNAME)
+endif
+endif
+endif
+ifdef EXTRAINSTALLFILES
+ @$(ECHO) -e $(addprefix "\n"$(DATAINSTALLDIR)/,$(EXTRAINSTALLFILES))
+endif
+
+fpc_install: $(INSTALLTARGET)
+# Create UnitInstallFiles
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(BININSTALLDIR)
+# Compress the exes if upx is defined
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILES)
+endif
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(BININSTALLDIR)
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(UNITINSTALLDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(UNITINSTALLDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(UNITINSTALLDIR)
+endif
+ifneq ($(wildcard $(LIBFULLNAME)),)
+ $(MKDIR) $(LIBINSTALLDIR)
+ $(INSTALL) $(LIBFULLNAME) $(LIBINSTALLDIR)
+ifdef inUnix
+ ln -sf $(LIBFULLNAME) $(LIBINSTALLDIR)/$(LIBNAME)
+endif
+endif
+endif
+ifdef EXTRAINSTALLFILES
+ $(MKDIR) $(DATAINSTALLDIR)
+ $(INSTALL) $(EXTRAINSTALLFILES) $(DATAINSTALLDIR)
+endif
+
+#####################################################################
+# SourceInstall rules
+#####################################################################
+
+.PHONY: fpc_sourceinstall
+
+ifndef SOURCETOPDIR
+SOURCETOPDIR=$(BASEDIR)
+endif
+
+fpc_sourceinstall: clean
+ $(MKDIR) $(SOURCEINSTALLDIR)
+ $(COPYTREE) $(SOURCETOPDIR) $(SOURCEINSTALLDIR)
+
+#####################################################################
+# exampleinstall rules
+#####################################################################
+
+.PHONY: fpc_exampleinstall
+
+fpc_exampleinstall: $(addsuffix _clean,$(EXAMPLEDIROBJECTS))
+ifdef EXAMPLESOURCEFILES
+ $(MKDIR) $(EXAMPLEINSTALLDIR)
+ $(COPY) $(EXAMPLESOURCEFILES) $(EXAMPLEINSTALLDIR)
+endif
+ifdef EXAMPLEDIROBJECTS
+ifndef EXAMPLESOURCEFILES
+ $(MKDIR) $(EXAMPLEINSTALLDIR)
+endif
+ $(COPYTREE) $(addsuffix /*,$(EXAMPLEDIROBJECTS)) $(EXAMPLEINSTALLDIR)
+endif
+
+#####################################################################
+# Zip
+#####################################################################
+
+.PHONY: fpc_zipinstall
+
+# Create suffix to add
+ifndef PACKAGESUFFIX
+PACKAGESUFFIX=$(OS_TARGET)
+ifeq ($(OS_TARGET),go32v2)
+PACKAGESUFFIX=go32
+endif
+ifeq ($(OS_TARGET),win32)
+PACKAGESUFFIX=w32
+endif
+endif
+
+# Temporary path to pack a file
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/pack_tmp
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+
+# Maybe create default zipname from packagename
+ifndef ZIPNAME
+ifdef PACKAGENAME
+ZIPNAME=$(PACKAGEPREFIX)$(PACKAGENAME)$(PACKAGESUFFIX)
+endif
+endif
+
+# Use tar by default under linux
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+
+fpc_zipinstall:
+ifndef ZIPNAME
+ @$(ECHO) "Please specify ZIPNAME!"
+ @exit 1
+else
+ $(MAKE) $(ZIPTARGET) PREFIXINSTALLDIR=$(PACKDIR)
+ifdef USETAR
+ $(DEL) $(DESTZIPDIR)/$(ZIPNAME)$(TAREXT)
+ cd $(PACKDIR) ; $(TARPROG) cf$(TAROPT) $(DESTZIPDIR)/$(ZIPNAME)$(TAREXT) * ; cd $(BASEDIR)
+else
+ $(DEL) $(DESTZIPDIR)/$(ZIPNAME)$(ZIPEXT)
+ cd $(PACKDIR) ; $(ZIPPROG) -Dr $(ZIPOPT) $(DESTZIPDIR)/$(ZIPNAME)$(ZIPEXT) * ; cd $(BASEDIR)
+endif
+ $(DELTREE) $(PACKDIR)
+endif
+
+.PHONY: fpc_zipsourceinstall
+
+fpc_zipsourceinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall PACKAGESUFFIX=src
+
+.PHONY: fpc_zipexampleinstall
+
+fpc_zipexampleinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall PACKAGESUFFIX=exm
+
+#####################################################################
+# Clean rules
+#####################################################################
+
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+
+ifdef EXTRACLEANUNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(EXTRACLEANUNITS))
+endif
+
+ifdef CLEANPPUFILES
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+# Get the .o and .a files created for the units
+ifdef PPUFILES
+CLEANPPULINKFILES:=$(shell $(PPUFILES) $(CLEANPPUFILES))
+else
+CLEANPPULINKFILES:=$(wildcard $(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(LIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))))
+endif
+override CLEANPPULINKFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES))
+endif
+
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef EXTRACLEANFILES
+ -$(DEL) $(EXTRACLEANFILES)
+endif
+ifdef LIBNAME
+ -$(DEL) $(LIBNAME) $(LIBFULLNAME)
+endif
+ -$(DEL) $(FPCMADE) $(PPAS) link.res $(FPCEXTFILE) $(REDIRFILE)
+
+fpc_distclean: fpc_clean
+
+# Also run clean first if targetdir is set. Unittargetdir is always
+# set if targetdir or unittargetdir is specified
+ifdef UNITTARGETDIR
+TARGETDIRCLEAN=fpc_clean
+endif
+
+fpc_cleanall: $(CLEANTARGET) $(TARGETDIRCLEAN)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) $(FPCMADE) $(PPAS) link.res $(FPCEXTFILE) $(REDIRFILE)
+
+#####################################################################
+# Info rules
+#####################################################################
+
+.PHONY: fpc_info fpc_cfginfo fpc_objectinfo fpc_toolsinfo fpc_installinfo \
+ fpc_dirinfo
+
+fpc_info: $(INFOTARGET)
+
+fpc_infocfg:
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC....... $(FPC)
+ @$(ECHO) Version... $(FPC_VERSION)
+ @$(ECHO) CPU....... $(CPU_TARGET)
+ @$(ECHO) Source.... $(OS_SOURCE)
+ @$(ECHO) Target.... $(OS_TARGET)
+ @$(ECHO)
+
+fpc_infoobjects:
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) LoaderObjects..... $(LOADEROBJECTS)
+ @$(ECHO) UnitObjects....... $(UNITOBJECTS)
+ @$(ECHO) ExeObjects........ $(EXEOBJECTS)
+ @$(ECHO)
+ @$(ECHO) ExtraCleanUnits... $(EXTRACLEANUNITS)
+ @$(ECHO) ExtraCleanFiles... $(EXTRACLEANFILES)
+ @$(ECHO)
+ @$(ECHO) ExtraInstallUnits. $(EXTRAINSTALLUNITS)
+ @$(ECHO) ExtraInstallFiles. $(EXTRAINSTALLFILES)
+ @$(ECHO)
+
+fpc_infoinstall:
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ifdef DATE
+ @$(ECHO) DateStr.............. $(DATESTR)
+endif
+ifdef PACKAGEPREFIX
+ @$(ECHO) PackagePrefix........ $(PACKAGEPREFIX)
+endif
+ifdef PACKAGENAME
+ @$(ECHO) PackageName.......... $(PACKAGENAME)
+endif
+ @$(ECHO) PackageSuffix........ $(PACKAGESUFFIX)
+ @$(ECHO)
+ @$(ECHO) BaseInstallDir....... $(BASEINSTALLDIR)
+ @$(ECHO) BinInstallDir........ $(BININSTALLDIR)
+ @$(ECHO) LibInstallDir........ $(LIBINSTALLDIR)
+ @$(ECHO) UnitInstallDir....... $(UNITINSTALLDIR)
+ @$(ECHO) SourceInstallDir..... $(SOURCEINSTALLDIR)
+ @$(ECHO) DocInstallDir........ $(DOCINSTALLDIR)
+ @$(ECHO) DataInstallDir....... $(DATAINSTALLDIR)
+ @$(ECHO)
+ @$(ECHO) DestZipDir........... $(DESTZIPDIR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO)
+
+#####################################################################
+# Local Makefile
+#####################################################################
+
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+
diff --git a/gfx/gdi/Makefile.fpc b/gfx/gdi/Makefile.fpc
new file mode 100644
index 00000000..f3807726
--- /dev/null
+++ b/gfx/gdi/Makefile.fpc
@@ -0,0 +1,36 @@
+#
+# Makefile.fpc for fpGFX Win32 GDI support
+#
+
+[package]
+name=fpgfx
+version=0.3
+
+[require]
+packages=fcl
+unitdir=.. ../emulayer
+
+[target]
+units=gfx_gdi gfxinterface
+rst=gfx_gdi
+
+[compiler]
+unitdir=.. ../emulayer
+unittargetdir=../units
+options=-S2h
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=/opt/fpc/src
+
+#[libs]
+#libname=fpgfx
+
+#[install]
+#subdir=
+
+#[dirs]
+#fpcdir=../../../..
+#unitdir=..
diff --git a/gfx/gdi/fpgfxpackage.lpk b/gfx/gdi/fpgfxpackage.lpk
new file mode 100644
index 00000000..1753eacc
--- /dev/null
+++ b/gfx/gdi/fpgfxpackage.lpk
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <Package Version="2">
+ <PathDelim Value="\"/>
+ <Name Value="fpGFXPackage"/>
+ <Author Value="Graeme Geldenhuys"/>
+ <CompilerOptions>
+ <Version Value="5"/>
+ <PathDelim Value="\"/>
+ <SearchPaths>
+ <OtherUnitFiles Value="..\;..\emulayer\"/>
+ <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+ <SrcPath Value="$(TargetOS)\"/>
+ </SearchPaths>
+ <CodeGeneration>
+ <Generate Value="Faster"/>
+ </CodeGeneration>
+ <Other>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+ <Description Value="Free Pascal GFX Library - [Windows]
+"/>
+ <License Value="LGPL
+"/>
+ <Version Minor="3"/>
+ <Files Count="6">
+ <Item1>
+ <Filename Value="..\gfxbase.pas"/>
+ <UnitName Value="GfxBase"/>
+ </Item1>
+ <Item2>
+ <Filename Value="..\emulayer\geldirty.pas"/>
+ <UnitName Value="GELDirty"/>
+ </Item2>
+ <Item3>
+ <Filename Value="..\emulayer\gelimage.pas"/>
+ <UnitName Value="GELImage"/>
+ </Item3>
+ <Item4>
+ <Filename Value="gfxinterface.pas"/>
+ <UnitName Value="GFXInterface"/>
+ </Item4>
+ <Item5>
+ <Filename Value="gfx_gdi.pas"/>
+ <UnitName Value="GFX_GDI"/>
+ </Item5>
+ <Item6>
+ <Filename Value="..\fpgfx.pas"/>
+ <UnitName Value="fpgfx"/>
+ </Item6>
+ </Files>
+ <RequiredPkgs Count="1">
+ <Item1>
+ <PackageName Value="FCL"/>
+ <MinVersion Major="1" Valid="True"/>
+ </Item1>
+ </RequiredPkgs>
+ <UsageOptions>
+ <UnitPath Value="$(PkgOutDir)\"/>
+ </UsageOptions>
+ <PublishOptions>
+ <Version Value="2"/>
+ <DestinationDirectory Value="$(TestDir)\publishedpackage\"/>
+ <IgnoreBinaries Value="False"/>
+ </PublishOptions>
+ </Package>
+</CONFIG>
diff --git a/gfx/gdi/fpgfxpackage.pas b/gfx/gdi/fpgfxpackage.pas
new file mode 100644
index 00000000..f4f1dc00
--- /dev/null
+++ b/gfx/gdi/fpgfxpackage.pas
@@ -0,0 +1,14 @@
+{ This file was automatically created by Lazarus. Do not edit!
+This source is only used to compile and install the package.
+ }
+
+unit fpGFXPackage;
+
+interface
+
+uses
+ GfxBase, GELDirty, GELImage, GFXInterface, GFX_GDI, fpgfx;
+
+implementation
+
+end.
diff --git a/gfx/gdi/gdikeys.inc b/gfx/gdi/gdikeys.inc
new file mode 100644
index 00000000..e6bd065c
--- /dev/null
+++ b/gfx/gdi/gdikeys.inc
@@ -0,0 +1,330 @@
+{
+ fpGFX - Free Pascal Graphics Library
+ Copyright (C) 2000 - 2001 by
+ Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org
+ Copyright (C) 2006 by Graeme Geldenhuys
+ member of the fpGFX development team.
+
+ Win32 GDI target implementation: Keycode translation helpers
+
+ See the file COPYING.modifiedLGPL, included in this distribution,
+ for details about the copyright.
+
+ This program 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.
+
+ **********************************************************************}
+
+
+function VirtKeyToKeycode(VirtKey: Byte): Word;
+const
+ TranslTable: array[Byte] of Integer = (
+ -1, // $00
+ -1, // $01 VK_LBUTTON
+ -1, // $02 VK_RBUTTON
+ -1, // $03 VK_CANCEL
+ -1, // $04 VK_MBUTTON
+ -1, // $05 VK_XBUTTON1
+ -1, // $06 VK_XBUTTON2
+ -1, // $07
+ keyBackSpace, // $08 VK_BACK
+ keyTab, // $09 VK_TAB
+ -1, // $0a
+ -1, // $0b
+ keyClear, // $0c VK_CLEAR
+ keyReturn, // $0d VK_RETURN
+ -1, // $0e
+ -1, // $0f
+ keyShift, // $10 VK_SHIFT
+ keyCtrl, // $11 VK_CONTROL
+ keyAlt, // $12 VK_MENU
+ keyPause, // $13 VK_PAUSE
+ -1, // $14 VK_CAPITAL
+ -1, // $15 VK_KANA
+ -1, // $16
+ -1, // $17 VK_JUNJA
+ -1, // $18 VK_FINAL
+ -1, // $19 VK_HANJA
+ -1, // $1a
+ keyEscape, // $1b VK_ESCAPE
+ -1, // $1c VK_CONVERT
+ -1, // $1d VK_NONCONVERT
+ -1, // $1e VK_ACCEPT
+ keyModeSwitch, // $1f VK_MODECHANGE
+ $20, // $20 VK_SPACE
+ keyPrior, // $21 VK_PRIOR
+ keyNext, // $22 VK_NEXT
+ keyEnd, // $23 VK_END
+ keyHome, // $24 VK_HOME
+ keyLeft, // $25 VK_LEFT
+ keyUp, // $26 VK_UP
+ keyRight, // $27 VK_RIGHT
+ keyDown, // $28 VK_DOWN
+ keySelect, // $29 VK_SELECT
+ keyPrintScreen, // $2a VK_PRINT
+ keyExecute, // $2b VK_EXECUTE
+ keyPrintScreen, // $2c VK_SNAPSHOT
+ keyInsert, // $2d VK_INSERT
+ keyDelete, // $2e VK_DELETE
+ keyHelp, // $2f VK_HELP
+ $30, // $30 '0'
+ $31, // $31 '1'
+ $32, // $32 '2'
+ $33, // $33 '3'
+ $34, // $34 '4'
+ $35, // $35 '5'
+ $36, // $36 '6'
+ $37, // $37 '7'
+ $38, // $38 '8'
+ $39, // $39 '9'
+ -1, // $3a
+ -1, // $3b
+ -1, // $3c
+ -1, // $3d
+ -1, // $3e
+ -1, // $3f
+ -1, // $40
+ $41, // $41 'A'
+ $42, // $42 'B'
+ $43, // $43 'C'
+ $44, // $44 'D'
+ $45, // $45 'E'
+ $46, // $46 'F'
+ $47, // $47 'G'
+ $48, // $48 'H'
+ $49, // $49 'I'
+ $4a, // $4a 'J'
+ $4b, // $4b 'K'
+ $4c, // $4c 'L'
+ $4d, // $4d 'M'
+ $4e, // $4e 'N'
+ $4f, // $4f 'O'
+ $50, // $50 'P'
+ $51, // $51 'Q'
+ $52, // $52 'R'
+ $53, // $53 'S'
+ $54, // $54 'T'
+ $55, // $55 'U'
+ $56, // $56 'V'
+ $57, // $57 'W'
+ $58, // $58 'X'
+ $59, // $59 'Y'
+ $5a, // $5a 'Z'
+ -1, // $5b VK_LWIN
+ -1, // $5c VK_RWIN
+ -1, // $5d VK_APPS
+ -1, // $5e
+ -1, // $5f VK_SLEEP
+ keyP0, // $60 VK_NUMPAD0
+ keyP1, // $61 VK_NUMPAD1
+ keyP2, // $62 VK_NUMPAD2
+ keyP3, // $63 VK_NUMPAD3
+ keyP4, // $64 VK_NUMPAD4
+ keyP5, // $65 VK_NUMPAD5
+ keyP6, // $66 VK_NUMPAD6
+ keyP7, // $67 VK_NUMPAD7
+ keyP8, // $68 VK_NUMPAD8
+ keyP9, // $69 VK_NUMPAD9
+ keyPAsterisk, // $6a VK_MULTIPLY
+ keyPPlus, // $6b VK_ADD
+ keyPSeparator, // $6c VK_SEPARATOR
+ keyPMinus, // $6d VK_SUBTRACT
+ keyPDecimal, // $6e VK_DECIMAL
+ keyPSlash, // $6f VK_DIVIDE
+ keyF1, // $70 VK_F1
+ keyF2, // $71 VK_F2
+ keyF3, // $72 VK_F3
+ keyF4, // $73 VK_F4
+ keyF5, // $74 VK_F5
+ keyF6, // $75 VK_F6
+ keyF7, // $76 VK_F7
+ keyF8, // $77 VK_F8
+ keyF9, // $78 VK_F9
+ keyF10, // $79 VK_F10
+ keyF11, // $7a VK_F11
+ keyF12, // $7b VK_F12
+ keyF13, // $7c VK_F13
+ keyF14, // $7d VK_F14
+ keyF15, // $7e VK_F15
+ keyF16, // $7f VK_F16
+ keyF17, // $80 VK_F17
+ keyF18, // $81 VK_F18
+ keyF19, // $82 VK_F19
+ keyF20, // $83 VK_F20
+ keyF21, // $84 VK_F21
+ keyF22, // $85 VK_F22
+ keyF23, // $86 VK_F23
+ keyF24, // $87 VK_F24
+ -1, // $88
+ -1, // $89
+ -1, // $8a
+ -1, // $8b
+ -1, // $8c
+ -1, // $8d
+ -1, // $8e
+ -1, // $8f
+ keyNumLock, // $90 VK_NUMLOCK
+ keyScroll, // $91 VK_SCROLL
+ -1, // $92 VK_OEM_NEC_EQUAL
+ -1, // $93 VK_OEM_FJ_MASSHOU
+ -1, // $94 VK_OEM_FJ_TOUROKU
+ -1, // $95 VK_OEM_FJ_LOYA
+ -1, // $96 VK_OEM_FJ_ROYA
+ -1, // $97
+ -1, // $98
+ -1, // $99
+ -1, // $9a
+ -1, // $9b
+ -1, // $9c
+ -1, // $9d
+ -1, // $9e
+ -1, // $9f
+ keyShiftL, // $a0 VK_LSHIFT
+ keyShiftR, // $a1 VK_RSHIFT
+ keyCtrlL, // $a2 VK_LCONTROL
+ keyCtrlR, // $a3 VK_RCONTROL
+ -1, // $a4 VK_LMENU
+ -1, // $a5 VK_RMENU
+ -1, // $a6 VK_BROWSER_BACK
+ -1, // $a7 VK_BROWSER_FORWARD
+ -1, // $a8 VK_BROWSER_REFRESH
+ -1, // $a9 VK_BROWSER_STOP
+ -1, // $aa VK_BROWSER_SEARCH
+ -1, // $ab VK_BROWSER_FAVORITES
+ -1, // $ac VK_BROWSER_HOME
+ -1, // $ad VK_VOLUME_MUTE
+ -1, // $ae VK_VOLUME_DOWN
+ -1, // $af VK_VOLUME_UP
+ -1, // $b0 VK_MEDIA_NEXT_TRACK
+ -1, // $b1 VK_MEDIA_PREV_TRACK
+ -1, // $b2 VK_MEDIA_STOP
+ -1, // $b3 VK_MEDIA_PLAY_PAUSE
+ -1, // $b4 VK_LAUNCH_MAIL
+ -1, // $b5 VK_LAUNCH_MEDIA_SELECT
+ -1, // $b6 VK_LAUNCH_APP1
+ -1, // $b7 VK_LAUNCH_APP2
+ -1, // $b8
+ -1, // $b9
+ $dc, {U Umlaut} // $ba VK_OEM_1
+ $2b, {+ char} // $bb VK_OEM_PLUS
+ $2c, {, char} // $bc VK_OEM_COMMA
+ $2d, {- char} // $bd VK_OEM_MINUS
+ $2e, {. char} // $be VK_OEM_PERIOD
+ $23, {# char} // $bf VK_OEM_2
+ $d6, {O Umlaut} // $c0 VK_OEM_3
+ -1, // $c1
+ -1, // $c2
+ -1, // $c3
+ -1, // $c4
+ -1, // $c5
+ -1, // $c6
+ -1, // $c7
+ -1, // $c8
+ -1, // $c9
+ -1, // $ca
+ -1, // $cb
+ -1, // $cc
+ -1, // $cd
+ -1, // $ce
+ -1, // $cf
+ -1, // $d0
+ -1, // $d1
+ -1, // $d2
+ -1, // $d3
+ -1, // $d4
+ -1, // $d5
+ -1, // $d6
+ -1, // $d7
+ -1, // $d8
+ -1, // $d9
+ -1, // $da
+ -1, // $db VK_OEM_4
+ keyDeadCircumflex, // $dc VK_OEM_5
+ keyDeadAcute, // $dd VK_OEM_6
+ $c4, {A Umlaut} // $de VK_OEM_7
+ -1, // $df VK_OEM_8
+ -1, // $e0
+ -1, // $e1 VK_OEM_AX
+ $3c, {< char} // $e2 VK_OEM_102
+ -1, // $e3 VK_ICO_HELP
+ keyP5, // $e4 VK_ICO_00
+ -1, // $e5 VK_PROCESSKEY
+ -1, // $e6 VK_ICO_CLEAR
+ -1, // $e7 VK_PACKET
+ -1, // $e8
+ -1, // $e9 VK_OEM_RESET
+ -1, // $ea VK_OEM_JUMP
+ -1, // $eb VK_OEM_PA1
+ -1, // $ec VK_OEM_PA2
+ -1, // $ed VK_OEM_PA3
+ -1, // $ee VK_OEM_WSCTRL
+ -1, // $ef VK_OEM_CUSEL
+ -1, // $f0 VK_OEM_ATTN
+ -1, // $f1 VK_OEM_FINISH
+ -1, // $f2 VK_OEM_COPY
+ -1, // $f3 VK_OEM_AUTO
+ -1, // $f4 VK_OEM_ENLW
+ -1, // $f5 VK_OEM_BACKTAB
+ -1, // $f6 VK_ATTN
+ -1, // $f7 VK_CRSEL
+ -1, // $f8 VK_EXSEL
+ -1, // $f9 VK_EREOF
+ -1, // $fa VK_PLAY
+ -1, // $fb VK_ZOOM
+ -1, // $fc VK_NONAME
+ -1, // $fd VK_PA1
+ -1, // $fe VK_OEM_CLEAR
+ -1 // $ff
+ );
+begin
+ if TranslTable[VirtKey] = -1 then
+ begin
+{$IFDEF Debug}
+ WriteLn('No mapping for virtual keycode $', IntToHex(VirtKey, 2));
+{$ENDIF}
+ Result := keyNIL
+ end else
+ begin
+ Result := TranslTable[VirtKey];
+ // WriteLn('Key $', IntToHex(VirtKey, 2), ' mapped to $', IntToHex(Result, 4));
+ end;
+end;
+
+
+function GetKeyboardShiftState: TShiftState;
+var
+ State: array[Byte] of Byte;
+begin
+ Windows.GetKeyboardState(State);
+ Result := [];
+ if (State[VK_SHIFT] and 128) <> 0 then
+ Include(Result, ssShift);
+ if (State[VK_MENU] and 128) <> 0 then
+ Include(Result, ssAlt);
+ if (State[VK_CONTROL] and 128) <> 0 then
+ Include(Result, ssCtrl);
+ if (State[VK_LBUTTON] and 128) <> 0 then
+ Include(Result, ssLeft);
+ if (State[VK_RBUTTON] and 128) <> 0 then
+ Include(Result, ssRight);
+ if (State[VK_MBUTTON] and 128) <> 0 then
+ Include(Result, ssMiddle);
+ if (State[VK_CAPITAL] and 1) <> 0 then
+ Include(Result, ssCaps);
+ if (State[VK_NUMLOCK] and 1) <> 0 then
+ Include(Result, ssNum);
+ if (State[VK_SCROLL] and 1) <> 0 then
+ Include(Result, ssScroll);
+end;
+
+
+{
+ $Log: gdikeys.inc,v $
+ Revision 1.2 2001/02/09 20:44:59 sg
+ * Fixed lots of keyboard mapping bugs
+
+ Revision 1.1 2001/01/11 23:07:24 sg
+ *** empty log message ***
+
+}
diff --git a/gfx/gdi/gfx_gdi.pas b/gfx/gdi/gfx_gdi.pas
new file mode 100644
index 00000000..10945b54
--- /dev/null
+++ b/gfx/gdi/gfx_gdi.pas
@@ -0,0 +1,1730 @@
+{
+ fpGUI - Free Pascal GUI Library
+
+ GFX_GDI - Windows GDI specific code
+
+ Copyright (C) 2000 - 2006 See the file AUTHORS, included in this
+ distribution, for details of the copyright.
+
+ See the file COPYING.modifiedLGPL, included in this distribution,
+ for details about redistributing fpGUI.
+
+ This program 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.
+}
+unit GFX_GDI;
+
+{$ifdef fpc}
+ {$mode delphi}{$H+}
+{$endif}
+
+interface
+
+uses
+ Windows,
+ SysUtils, Classes,
+ GfxBase;
+
+
+resourcestring
+ SGDICanvasInvalidFontClass =
+ 'Tried to set font of class "%s" into GDI context. '
+ + 'Only TGDIFont is allowed.';
+
+{ Constants missing on windows unit }
+const
+ WM_MOUSEWHEEL = $020a;
+
+ VER_PLATFORM_WIN32_CE = 3;
+
+{ Unicode selection variables }
+var
+ UnicodeEnabledOS: Boolean;
+
+ WinVersion: TOSVersionInfo;
+
+type
+
+ EGDIError = class(EGfxError);
+
+ { TGDIFont }
+
+ TGDIFont = class(TFCustomFont)
+ public
+ class function GetDefaultFontName(const AFontClass: TGfxFontClass): String; override;
+ constructor Create(const Descriptor: String);
+ destructor Destroy; override;
+ end;
+
+
+ { TGDICanvas }
+
+ PGDICanvasState = ^TGDICanvasState;
+ TGDICanvasState = record
+ Prev: PGDICanvasState;
+ Matrix: TGfxMatrix;
+ Color, PenColor, FontColor: TGfxPixel;
+ PenLineStyle: TGfxLineStyle;
+ Font: TFCustomFont;
+ CurFontHandle: HFONT;
+ end;
+
+ TGDICanvas = class(TFCustomCanvas)
+ private
+ FHandle: HDC;
+ FColor, FBrushColor, FPenColor, FFontColor: TGfxPixel;
+ FLineStyle, FPenLineStyle: TGfxLineStyle;
+ FBrush, FOldBrush: HBRUSH;
+ FPen, FOldPen: HPEN;
+ FFont: TFCustomFont;
+ FFontHandle, FDefaultFontHandle, FCurFontHandle: HFONT;
+ FFontMetrics: TTextMetric;
+ FStateStackpointer: PGDICanvasState;
+ procedure Resized(NewWidth, NewHeight: Integer);
+ protected
+ function DoExcludeClipRect(const ARect: TRect): Boolean; override;
+ function DoIntersectClipRect(const ARect: TRect): Boolean; override;
+ function DoUnionClipRect(const ARect: TRect): Boolean; override;
+ function DoGetClipRect: TRect; override;
+ procedure NeedBrush;
+ procedure NeedPen;
+ procedure NeedFont(ANeedFontColor: Boolean);
+ procedure NeedFontColor;
+ procedure DoDrawArc(const ARect: TRect; StartAngle, EndAngle: Single); override;
+ procedure DoDrawCircle(const ARect: TRect); override;
+ procedure DoDrawLine(const AFrom, ATo: TPoint); override;
+ procedure DoDrawPoint(const APoint: TPoint); override;
+ procedure DoFillRect(const ARect: TRect); override;
+ procedure DoTextOut(const APosition: TPoint; const AText: String); override;
+ procedure DoCopyRect(ASource: TFCustomCanvas; const ASourceRect: TRect; const ADestPos: TPoint); override;
+ procedure DoMaskedCopyRect(ASource, AMask: TFCustomCanvas; const ASourceRect: TRect; const AMaskPos, ADestPos: TPoint); override;
+ procedure DoDrawImageRect(AImage: TFCustomImage; ASourceRect: TRect; const ADestPos: TPoint); override;
+ public
+ constructor Create(AHandle: HDC);
+ destructor Destroy; override;
+ function MapColor(const AColor: TGfxColor): TGfxPixel; override;
+ function FontCellHeight: Integer; override;
+ function TextExtent(const AText: String): TSize; override;
+ procedure SaveState; override;
+ procedure RestoreState; override;
+ procedure EmptyClipRect; override;
+ procedure SetColor_(AColor: TGfxPixel); override;
+ procedure SetFont(AFont: TFCustomFont); override;
+ procedure SetLineStyle(ALineStyle: TGfxLineStyle); override;
+ property Handle: HDC read FHandle;
+ end;
+
+
+ TGDIWindowCanvas = class(TGDICanvas)
+ private
+ FWnd: HWND;
+ public
+ constructor Create(AWnd: HWND);
+ destructor Destroy; override;
+ end;
+
+
+ TGDIBitmapCanvas = class(TGDICanvas)
+ private
+ FBitmap, FOldBitmap: HBITMAP;
+ public
+ constructor Create(ABitmap: HBITMAP; AWidth, AHeight: Integer);
+ destructor Destroy; override;
+ property Bitmap: HBITMAP read FBitmap;
+ end;
+
+ { TGDIImage }
+
+ TGDIImage = class(TFCustomImage)
+ private
+ FHandle: HBITMAP;
+ IsLocked: Boolean;
+ protected
+ FStride: LongWord;
+ FData: Pointer;
+ public
+ constructor Create(AWidth, AHeight: Integer; APixelFormat: TGfxPixelFormat); override;
+ destructor Destroy; override;
+ procedure Lock(var AData: Pointer; var AStride: LongWord); override;
+ procedure Unlock; override;
+ property Handle: HBITMAP read FHandle;
+ property Stride: LongWord read FStride;
+ property Data: Pointer read FData;
+ end;
+
+ { TGDIScreen }
+
+ TGDIScreen = class(TFCustomScreen)
+ public
+ constructor Create; override;
+ end;
+
+
+ { TGDIApplication }
+
+ TGDIApplication = class(TFCustomApplication)
+ private
+ DoBreakRun: Boolean;
+ public
+ { default methods }
+ constructor Create; override;
+ destructor Destroy; override;
+ procedure AddWindow(AWindow: TFCustomWindow); override;
+ procedure Initialize(ADisplayName: String = ''); override;
+ procedure Run; override;
+ procedure Quit; override;
+ end;
+
+ { TGDIWindow }
+
+ TGDIWindow = class(TFCustomWindow)
+ private
+ FMinSize, FMaxSize: TSize;
+ FParent: TFCustomWindow;
+ { Messages }
+ procedure WMCreate(var Msg: TMessage); message WM_CREATE;
+ procedure WMDestroy(var Msg: TMessage); message WM_DESTROY;
+ procedure WMGetMinMaxInfo(var Msg: TMessage); message WM_GETMINMAXINFO;
+ procedure WMActivate(var Msg: TMessage); message WM_ACTIVATE;
+ procedure WMPaint(var Msg: TMessage); message WM_PAINT;
+ procedure WMShowWindow(var Msg: TMessage); message WM_SHOWWINDOW;
+ procedure WMMove(var Msg: TMessage); message WM_MOVE;
+ procedure WMSize(var Msg: TMessage); message WM_SIZE;
+ { Input messages }
+ procedure WMLButtonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
+ procedure WMLButtonUp(var Msg: TMessage); message WM_LBUTTONUP;
+ procedure WMRButtonDown(var Msg: TMessage); message WM_RBUTTONDOWN;
+ procedure WMRButtonUp(var Msg: TMessage); message WM_RBUTTONUP;
+ procedure WMMButtonDown(var Msg: TMessage); message WM_MBUTTONDOWN;
+ procedure WMMButtonUp(var Msg: TMessage); message WM_MBUTTONUP;
+ procedure WMMouseMove(var Msg: TMessage); message WM_MOUSEMOVE;
+ procedure WMMouseWheel(var Msg: TMessage); message WM_MOUSEWHEEL;
+ procedure WMKeyDown(var Msg: TMessage); message WM_KEYDOWN;
+ procedure WMKeyUp(var Msg: TMessage); message WM_KEYUP;
+ procedure WMChar(var Msg: TMessage); message WM_CHAR;
+ procedure WMSysKeyDown(var Msg: TMessage); message WM_SYSKEYDOWN;
+ procedure WMSysKeyUp(var Msg: TMessage); message WM_SYSKEYUP;
+ procedure WMSysChar(var Msg: TMessage); message WM_SYSCHAR;
+ protected
+ WindowClass: TWndClass;
+ WindowClassW: TWndClassW;
+ FWindowStyle, FWindowStyleEx: LongWord;
+ FMouseInWindow, FHasMouseCapture, FHasFocus: Boolean;
+ function GetTitle: String; override;
+ procedure SetTitle(const ATitle: String); override;
+ procedure DoSetCursor; override;
+ procedure UpdateWindowButtons;
+ function DoMouseEnterLeaveCheck(const Msg: TMessage): Boolean;
+ public
+ constructor Create(AParent: TFCustomWindow; AWindowOptions: TGfxWindowOptions);
+ destructor Destroy; override;
+ procedure DefaultHandler(var Message); override;
+ procedure SetPosition(const APosition: TPoint); override;
+ procedure SetSize(const ASize: TSize); override;
+ procedure SetMinMaxSize(const AMinSize, AMaxSize: TSize); override;
+ procedure SetClientSize(const ASize: TSize); override;
+ procedure SetMinMaxClientSize(const AMinSize, AMaxSize: TSize); override;
+ procedure Show; override;
+ procedure Invalidate(const ARect: TRect); override;
+ procedure PaintInvalidRegion; override;
+ procedure CaptureMouse; override;
+ procedure ReleaseMouse; override;
+ end;
+
+
+function RectToWinRect(const ARect: TRect): Windows.Rect;
+function WinRectToRect(const ARect: Windows.Rect): TRect;
+
+function VirtKeyToKeycode(VirtKey: Byte): Word;
+function GetKeyboardShiftState: TShiftState;
+
+
+implementation
+
+uses
+ math, fpgfx;
+
+{
+ Use CenterPoint to get the Center-Point of any rectangle. It is primarily
+ for use with, and in, other routines such as Quadrant, and RadialPoint.
+}
+function CenterPoint(Rect : TRect) : TPoint;
+var
+ Tmp : Longint;
+begin
+ With Rect do begin
+
+ If Right < Left then begin
+ Tmp := Right;
+ Right := Left;
+ Left := Tmp;
+ end;
+
+ If Bottom < Top then begin
+ Tmp := Bottom;
+ Bottom := Top;
+ Top := Tmp;
+ end;
+
+ Result.X := Left + (Right - Left) div 2;
+ Result.Y := Top + (Bottom - Top) div 2;
+ end;
+end;
+
+
+{
+ Use LineEndPoint to get the End-Point of a line of any given Length at
+ any given angle with any given Start-Point. It is primarily for use in
+ other routines such as RadialPoint. The angle is in 1/16th of a degree.
+ For example, a full circle equals 5760 (16*360). Zero degrees is at the
+ 3'o clock position.
+}
+Function LineEndPoint(StartPoint : TPoint; Angle, Length : Extended) :
+TPoint;
+begin
+ if Angle > 360*16 then
+ Angle := Frac(Angle / 360*16) * 360*16;
+
+ if Angle < 0 then
+ Angle := 360*16 - abs(Angle);
+
+ Result.Y := StartPoint.Y - Round(Length*Sin(DegToRad(Angle/16)));
+ Result.X := StartPoint.X + Round(Length*Cos(DegToRad(Angle/16)));
+end;
+
+
+{
+ Use EllipseRadialLength to get the Radial-Length of non-rotated ellipse at
+ any given Eccentric( aka Radial ) Angle. It is primarily for use in other
+ routines such as RadialPoint. The Eccentric angle is in 1/16th of a degree.
+ For example, a full circle equals 5760 (16*360). Zero degrees is at the
+ 3'o clock position.
+}
+function EllipseRadialLength(Rect: TRect; EccentricAngle: Extended): Longint;
+var
+ a, b, R : Extended;
+begin
+ a := (Rect.Right - Rect.Left) div 2;
+ b := (Rect.Bottom - Rect.Top) div 2;
+ R := Sqr(a)*Sqr(b);
+ R := Sqrt(R / ((Sqr(b)*Sqr(Cos(DegToRad(EccentricAngle/16))))
+ + (Sqr(a)*Sqr(Sin(DegToRad(EccentricAngle/16))))));
+ Result := integer(Trunc(R));
+end;
+
+
+{
+ Use RadialPoint to get the Radial-Point at any given Eccentric( aka Radial )
+ angle on any non-rotated ellipse. It is primarily for use in Angles2Coords.
+ The EccentricAngle is in 1/16th of a degree. For example, a full circle
+ equals 5760 (16*360). Zero degrees is at the 3'o clock position.
+}
+function RadialPoint(EccentricAngle: Extended; Rect: TRect): TPoint;
+var
+ R: Longint;
+Begin
+ R := EllipseRadialLength(Rect, EccentricAngle);
+ Result := LineEndPoint(CenterPoint(Rect), EccentricAngle, R);
+end;
+
+
+{
+ Use Angles2Coords to convert an Eccentric(aka Radial) Angle and an
+ Angle-Length, such as are used in X-Windows and GTK, into the coords,
+ for Start and End Radial-Points, such as are used in the Windows API Arc
+ Pie and Chord routines. The angles are 1/16th of a degree. For example, a
+ full circle equals 5760 (16*360). Positive values of Angle and AngleLength
+ mean counter-clockwise while negative values mean clockwise direction.
+ Zero degrees is at the 3'o clock position.
+}
+procedure Angles2Coords(X, Y, Width, Height: Integer; Angle1, Angle2: Extended;
+ var SX, SY, EX, EY: Integer);
+var
+ aRect: TRect;
+ SP, EP: TPoint;
+begin
+ aRect := Rect(X, Y, X + Width, Y + Height);
+ SP := RadialPoint(Angle1, aRect);
+ If Angle2 + Angle1 > 360*16 then
+ Angle2 := (Angle2 + Angle1) - 360*16
+ else
+ Angle2 := Angle2 + Angle1;
+ EP := RadialPoint(Angle2, aRect);
+ SX := SP.X;
+ SY := SP.Y;
+ EX := EP.X;
+ EY := EP.Y;
+end;
+
+
+{ TGDIFont }
+
+class function TGDIFont.GetDefaultFontName(const AFontClass: TGfxFontClass): String;
+const
+ FontNames: array[TGfxFontClass] of String = (
+ 'Times New Roman', 'Arial', 'Courier New', 'Wingdings');
+begin
+ Result := FontNames[AFontClass];
+end;
+
+constructor TGDIFont.Create(const Descriptor: String);
+type
+ TXLFDFields = (lfdFoundry, lfdFamily, lfdWeight, lfdSlant, lfdSetWidth,
+ lfdAddStyle, lfdPixelSize, lfdPointSize, lfdResolutionX, lfdResolutionY,
+ lfdSpacing, lfdAverageWidth, lfdCharsetRegistry, lfdCharsetEncoding);
+var
+ Fields: array[TXLFDFields] of String;
+ FontInfo: LOGFONT;
+ FieldIndex: TXLFDFields;
+ s: String;
+ i: Integer;
+ dc: HDC;
+begin
+ inherited Create;
+
+ // Split the font descriptor string
+ s := Descriptor;
+ for FieldIndex := Low(TXLFDFields) to High(TXLFDFields) do
+ begin
+ Fields[FieldIndex] := Copy(s, 2, Length(s));
+ i := Pos('-', Fields[FieldIndex]);
+ if i = 0 then
+ i := Length(s);
+ Fields[FieldIndex] := Copy(Fields[FieldIndex], 1, i - 1);
+ s := Copy(s, i + 1, Length(s));
+ end;
+
+ FillChar(FontInfo, SizeOf(FontInfo), 0);
+
+ if (Length(Fields[lfdPixelSize]) > 0) and (Fields[lfdPixelSize] <> '*') then
+ FontInfo.lfHeight := -StrToInt(Fields[lfdPixelSize])
+ else if (Length(Fields[lfdPointSize]) > 0) and
+ (Fields[lfdPointSize] <> '*') then
+ begin
+ dc := Windows.GetDC(0);
+ FontInfo.lfHeight := ((StrToInt(Fields[lfdPointSize]) *
+ Windows.GetDeviceCaps(dc, LOGPIXELSY)) + (5 * 72)) div 720;
+ Windows.ReleaseDC(0, dc);
+ end;
+
+ if (Length(Fields[lfdAverageWidth]) > 0) and
+ (Fields[lfdAverageWidth] <> '*') then
+ FontInfo.lfWidth := StrToInt(Fields[lfdAverageWidth]);
+
+ if CompareText(Fields[lfdWeight], 'medium') = 0 then
+ FontInfo.lfWeight := FW_MEDIUM
+ else if CompareText(Fields[lfdWeight], 'bold') = 0 then
+ FontInfo.lfWeight := FW_BOLD;
+
+ if (CompareText(Fields[lfdSlant], 'i') = 0) or
+ (CompareText(Fields[lfdSlant], 'o') = 0) then
+ FontInfo.lfItalic := 1;
+
+ if (CompareText(Fields[lfdSpacing], 'm') = 0) or
+ (CompareText(Fields[lfdSpacing], 'c') = 0) then
+ FontInfo.lfPitchAndFamily := FIXED_PITCH
+ else if CompareText(Fields[lfdSpacing], 'p') = 0 then
+ FontInfo.lfPitchAndFamily := VARIABLE_PITCH;
+
+ if Fields[lfdFamily] <> '*' then
+ FontInfo.lfFaceName := Fields[lfdFamily];
+
+ FHandle := Windows.CreateFontIndirect(@FontInfo);
+end;
+
+
+destructor TGDIFont.Destroy;
+begin
+ Windows.DeleteObject(Handle);
+ inherited Destroy;
+end;
+
+
+{ TGDICanvas }
+
+constructor TGDICanvas.Create(AHandle: HDC);
+begin
+ inherited Create;
+ FHandle := AHandle;
+ ASSERT(Handle <> 0);
+ FDefaultFontHandle := Windows.GetStockObject(DEFAULT_GUI_FONT);
+ FCurFontHandle := FDefaultFontHandle;
+ Windows.SelectObject(Handle, FDefaultFontHandle);
+ Windows.GetTextMetrics(Handle, @FFontMetrics);
+ Windows.SetBkMode(Handle, TRANSPARENT);
+end;
+
+
+destructor TGDICanvas.Destroy;
+begin
+ if FBrush <> 0 then
+ begin
+ Windows.SelectObject(Handle, FOldBrush);
+ Windows.DeleteObject(FBrush);
+ end;
+ if FPen <> 0 then
+ begin
+ Windows.SelectObject(Handle, FOldPen);
+ Windows.DeleteObject(FPen);
+ end;
+ inherited Destroy;
+end;
+
+
+procedure TGDICanvas.SaveState;
+var
+ SavedState: PGDICanvasState;
+ NewRegion: HRGN;
+begin
+ New(SavedState);
+ SavedState^.Prev := FStateStackpointer;
+ SavedState^.Matrix := Matrix;
+ SavedState^.Color := FColor;
+ SavedState^.PenColor := FPenColor;
+ SavedState^.PenLineStyle := FPenLineStyle;
+ SavedState^.FontColor := FFontColor;
+ SavedState^.Font := FFont;
+ SavedState^.CurFontHandle := FCurFontHandle;
+ FStateStackpointer := SavedState;
+ { !!!: This is very dangerous! Some of the FCurXXX variables are not saved in
+ SavedState, which might result in graphics errors under certain
+ circumstances. Better try to remove SaveDC/RestoreDC completely. }
+ Windows.SaveDC(Handle);
+end;
+
+
+procedure TGDICanvas.RestoreState;
+var
+ SavedState: PGDICanvasState;
+begin
+ Windows.RestoreDC(Handle, -1);
+
+ SavedState := FStateStackpointer;
+ FStateStackpointer := SavedState^.Prev;
+ Matrix := SavedState^.Matrix;
+ FColor := SavedState^.Color;
+ FPenColor := SavedState^.PenColor;
+ FPenLineStyle := SavedState^.PenLineStyle;
+ FFontColor := SavedState^.FontColor;
+ FCurFontHandle := SavedState^.CurFontHandle;
+ SetFont(SavedState^.Font);
+ Dispose(SavedState);
+end;
+
+
+procedure TGDICanvas.EmptyClipRect;
+begin
+ Windows.IntersectClipRect(Handle, 0, 0, 0, 0);
+end;
+
+
+function TGDICanvas.DoExcludeClipRect(const ARect: TRect): Boolean;
+begin
+ with ARect do
+ Result :=
+ Windows.ExcludeClipRect(Handle, Left, Top, Right, Bottom) <> NULLREGION;
+end;
+
+
+function TGDICanvas.DoIntersectClipRect(const ARect: TRect): Boolean;
+begin
+ with ARect do
+ Result :=
+ Windows.IntersectClipRect(Handle, Left, Top, Right, Bottom) <> NULLREGION
+end;
+
+
+function TGDICanvas.DoUnionClipRect(const ARect: TRect): Boolean;
+var
+ Region: HRGN;
+begin
+ with ARect do
+ Region := Windows.CreateRectRgn(Left, Top, Right, Bottom);
+ Result := Windows.ExtSelectClipRgn(Handle, Region, RGN_OR) <> NULLREGION;
+ Windows.DeleteObject(Region);
+end;
+
+
+function TGDICanvas.DoGetClipRect: TRect;
+var
+ Rect: Windows.Rect;
+begin
+ Windows.GetClipBox(Handle, Rect);
+ Result := TRect(Rect);
+end;
+
+
+function TGDICanvas.MapColor(const AColor: TGfxColor): TGfxPixel;
+begin
+{ Result := Windows.GetNearestColor(Handle, RGB(AColor.Red div 257,
+ AColor.Green div 257, AColor.Blue div 257));}
+ Result := RGB(AColor.Red div 257, AColor.Green div 257, AColor.Blue div 257);
+end;
+
+
+procedure TGDICanvas.SetColor_(AColor: TGfxPixel);
+begin
+ FColor := AColor;
+end;
+
+
+procedure TGDICanvas.SetFont(AFont: TFCustomFont);
+begin
+ if AFont = FFont then
+ exit;
+
+ FFont := AFont;
+
+ if not Assigned(AFont) then
+ FFontHandle := FDefaultFontHandle
+ else
+ begin
+ if not AFont.InheritsFrom(TGDIFont) then
+ raise EGfxError.CreateFmt(SGDICanvasInvalidFontClass, [AFont.ClassName]);
+ FFontHandle := TGDIFont(AFont).Handle;
+ end;
+end;
+
+
+procedure TGDICanvas.SetLineStyle(ALineStyle: TGfxLineStyle);
+begin
+ FLineStyle := ALineStyle;
+end;
+
+
+procedure TGDICanvas.DoDrawArc(const ARect: TRect; StartAngle, EndAngle: Single);
+var
+ SX, SY, EX, EY : Longint;
+begin
+ {$Warning DoDrawArc needs testing. }
+ Angles2Coords(ARect.Left, ARect.Top, ARect.Right - ARect.Left,
+ ARect.Bottom - ARect.Top, StartAngle, EndAngle, SX, SY, EX, EY);
+ Windows.Arc(Handle, ARect.Left, ARect.Top, ARect.Right,
+ ARect.Bottom, SX, SY, EX, EY)
+end;
+
+
+procedure TGDICanvas.DoDrawCircle(const ARect: TRect);
+begin
+ {$Warning DoDrawCircle needs testing. }
+ Windows.Ellipse(Handle, ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
+end;
+
+
+procedure TGDICanvas.DoDrawLine(const AFrom, ATo: TPoint);
+begin
+ NeedPen;
+ Windows.MoveToEx(Handle, AFrom.x, AFrom.y, nil);
+ Windows.LineTo(Handle, ATo.x, ATo.y);
+end;
+
+
+procedure TGDICanvas.DoDrawPoint(const APoint: TPoint);
+begin
+ {$Warning This is not implemented yet. }
+ // Use DrawLine() as windows doesn't have a DrawPoint. It does have a
+ // SetPixel() method, but not sure how to use it yet.
+ DoDrawLine(APoint, APoint);
+// DoFillRect(Rect(APoint.X, APoint.Y, APoint.X, APoint.Y));
+end;
+
+
+procedure TGDICanvas.DoFillRect(const ARect: TRect);
+var
+ r: Windows.Rect;
+begin
+ NeedBrush;
+ r := RectToWinRect(ARect);
+ Windows.FillRect(Handle, r, FBrush);
+end;
+
+
+function TGDICanvas.FontCellHeight: Integer;
+begin
+ NeedFont(False);
+ Result := FFontMetrics.tmHeight;
+end;
+
+
+function TGDICanvas.TextExtent(const AText: String): TSize;
+var
+ WideText: WideString;
+begin
+ NeedFont(False);
+
+ WideText := Utf8Decode(AText);
+ Windows.GetTextExtentPoint32W(Handle, PWideChar(WideText), Length(WideText), @Result)
+end;
+
+
+procedure TGDICanvas.DoTextOut(const APosition: TPoint; const AText: String);
+var
+ WideText: WideString;
+begin
+ NeedFont(True);
+
+ WideText := Utf8Decode(AText);
+ Windows.TextOutW(Handle, APosition.x, APosition.y, PWideChar(WideText), Length(WideText))
+end;
+
+
+procedure TGDICanvas.DoCopyRect(ASource: TFCustomCanvas; const ASourceRect: TRect;
+ const ADestPos: TPoint);
+begin
+ if not ASource.InheritsFrom(TGDICanvas) then
+ raise EGDIError.CreateFmt(SIncompatibleCanvasForBlitting,
+ [ASource.ClassName, Self.ClassName]);
+
+ Windows.BitBlt(
+ Handle, ADestPos.x, ADestPos.y, ASourceRect.Right - ASourceRect.Left,
+ ASourceRect.Bottom - ASourceRect.Top,
+ TGDICanvas(ASource).Handle, ASourceRect.Left, ASourceRect.Top,
+ SRCCOPY);
+end;
+
+
+procedure TGDICanvas.DoMaskedCopyRect(ASource, AMask: TFCustomCanvas;
+ const ASourceRect: TRect; const AMaskPos, ADestPos: TPoint);
+var
+ w, h: Integer;
+ SourceBitmap, AndObjectBitmap, AndMemBitmap, SaveBitmap,
+ OldSourceBitmap, OldAndObjectBitmap, OldAndMemBitmap,
+ OldSaveBitmap: HBITMAP;
+ SourceDC, MemDC, ObjectDC, SaveDC: HDC;
+begin
+ if not ASource.InheritsFrom(TGDICanvas) then
+ raise EGDIError.CreateFmt(SIncompatibleCanvasForBlitting,
+ [ASource.ClassName, Self.ClassName]);
+
+ if not AMask.InheritsFrom(TGDICanvas) then
+ raise EGDIError.CreateFmt(SIncompatibleCanvasForBlitting,
+ [AMask.ClassName, Self.ClassName]);
+
+ w := ASourceRect.Right - ASourceRect.Left;
+ h := ASourceRect.Bottom - ASourceRect.Top;
+
+ // See http://support.microsoft.com/support/kb/articles/Q79/2/12.ASP
+
+ SourceDC := Windows.CreateCompatibleDC(Handle);
+ ObjectDC := Windows.CreateCompatibleDC(Handle);
+ MemDC := Windows.CreateCompatibleDC(Handle);
+ SourceBitmap := Windows.CreateCompatibleBitmap(Handle, w, h);
+ AndObjectBitmap := Windows.CreateCompatibleBitmap(ObjectDC, w, h);
+ AndMemBitmap := Windows.CreateCompatibleBitmap(Handle, w, h);
+ OldSourceBitmap := Windows.SelectObject(SourceDC, SourceBitmap);
+ OldAndObjectBitmap := Windows.SelectObject(ObjectDC, AndObjectBitmap);
+ OldAndMemBitmap := Windows.SelectObject(MemDC, AndMemBitmap);
+
+ Windows.BitBlt(SourceDC, 0, 0, w, h,
+ TGDICanvas(ASource).Handle, ASourceRect.Left, ASourceRect.Top, SRCCOPY);
+ Windows.BitBlt(MemDC, 0, 0, w, h, Handle, ADestPos.x, ADestPos.y, SRCCOPY);
+
+ // !!!: Find a ROP for replacing the following 2 Blits with a single one:
+ Windows.BitBlt(ObjectDC, 0, 0, w, h,
+ TGDICanvas(AMask).Handle, AMaskPos.x, AMaskPos.y, NOTSRCCOPY);
+ Windows.BitBlt(MemDC, 0, 0, w, h, ObjectDC, 0, 0, SRCAND);
+
+ Windows.BitBlt(SourceDC, 0, 0, w, h,
+ TGDICanvas(AMask).Handle, AMaskPos.x, AMaskPos.y, SRCAND);
+ Windows.BitBlt(MemDC, 0, 0, w, h, SourceDC, 0, 0, SRCPAINT);
+ // Copy the result to the screen
+ Windows.BitBlt(Handle, ADestPos.x, ADestPos.y, w, h, MemDC, 0, 0, SRCCOPY);
+
+ // Clean up
+ Windows.DeleteObject(Windows.SelectObject(ObjectDC, OldAndObjectBitmap));
+ Windows.DeleteObject(Windows.SelectObject(MemDC, OldAndMemBitmap));
+ Windows.DeleteObject(Windows.SelectObject(SourceDC, OldSourceBitmap));
+ Windows.DeleteDC(MemDC);
+ Windows.DeleteDC(ObjectDC);
+ Windows.DeleteDC(SourceDC);
+end;
+
+
+procedure TGDICanvas.DoDrawImageRect(AImage: TFCustomImage; ASourceRect: TRect;
+ const ADestPos: TPoint);
+var
+ MemDC: HDC;
+ OldBitmap: HBITMAP;
+ GDIPal: array of PRGBQUAD;
+ i: Integer;
+begin
+ ASSERT(AImage.InheritsFrom(TGDIImage));
+ {$IFDEF Debug}
+ ASSERT(not TGDIImage(AImage).IsLocked);
+ {$ENDIF}
+
+ MemDC := Windows.CreateCompatibleDC(Handle);
+ OldBitmap := Windows.SelectObject(MemDC, TGDIImage(AImage).Handle);
+
+ // Set the color palette, if present
+ if Assigned(AImage.Palette) then
+ begin
+ GetMem(GDIPal, AImage.Palette.EntryCount * SizeOf(RGBQUAD));
+ for i := 0 to AImage.Palette.EntryCount - 1 do
+ with AImage.Palette.Entries[i] do
+ begin
+ GDIPal[i].rgbRed := Red div 257;
+ GDIPal[i].rgbGreen := Green div 257;
+ GDIPal[i].rgbBlue := Blue div 257;
+ GDIPal[i].rgbReserved := 0;
+ end;
+ Windows.SetDIBColorTable(MemDC, 0, AImage.Palette.EntryCount, GDIPal[0]^);
+ FreeMem(GDIPal);
+ end;
+
+ with ASourceRect do
+ Windows.BitBlt(Handle, ADestPos.x, ADestPos.y, Right - Left, Bottom - Top,
+ MemDC, Left, Top, SRCCOPY);
+
+ Windows.SelectObject(MemDC, OldBitmap);
+ Windows.DeleteDC(MemDC);
+end;
+
+
+procedure TGDICanvas.NeedBrush;
+begin
+ if (FBrush = 0) or (FBrushColor <> FColor) then
+ begin
+ if FBrush <> 0 then
+ begin
+ Windows.SelectObject(Handle, FOldBrush);
+ Windows.DeleteObject(FBrush);
+ end;
+ FBrushColor := FColor;
+ FBrush := Windows.CreateSolidBrush(FBrushColor);
+ FOldBrush := Windows.SelectObject(Handle, FBrush);
+ end;
+end;
+
+
+procedure TGDICanvas.NeedPen;
+begin
+ if (FPen = 0) or (FPenColor <> FColor) or (FPenLineStyle <> FLineStyle) then
+ begin
+ if FPen <> 0 then
+ begin
+ Windows.SelectObject(Handle, FOldPen);
+ Windows.DeleteObject(FPen);
+ end;
+ FPenColor := FColor;
+ FPenLineStyle := FLineStyle;
+ case FPenLineStyle of
+ lsSolid:
+ FPen := Windows.CreatePen(PS_SOLID, 0, FPenColor);
+ end;
+ FOldPen := Windows.SelectObject(Handle, FPen);
+ end;
+end;
+
+
+procedure TGDICanvas.NeedFont(ANeedFontColor: Boolean);
+begin
+ if FCurFontHandle <> FFontHandle then
+ begin
+ Windows.SelectObject(Handle, FFontHandle);
+ { TODO : Store the font metrics in TGDIFont }
+ Windows.GetTextMetrics(Handle, @FFontMetrics);
+ FCurFontHandle := FFontHandle;
+ end;
+ if ANeedFontColor then
+ NeedFontColor;
+end;
+
+
+procedure TGDICanvas.NeedFontColor;
+begin
+ if FFontColor <> FColor then
+ begin
+ FFontColor := FColor;
+ Windows.SetTextColor(Handle, FFontColor);
+ end;
+end;
+
+
+procedure TGDICanvas.Resized(NewWidth, NewHeight: Integer);
+begin
+ FWidth := NewWidth;
+ FHeight := NewHeight;
+end;
+
+
+{ TGDIWindowCanvas }
+
+constructor TGDIWindowCanvas.Create(AWnd: HWND);
+begin
+ FWnd := AWnd;
+ inherited Create(Windows.GetDC(FWnd));
+end;
+
+
+destructor TGDIWindowCanvas.Destroy;
+begin
+ inherited Destroy;
+ if Handle <> 0 then
+ Windows.ReleaseDC(FWnd, Handle);
+end;
+
+
+{ TGDIBitmapCanvas }
+
+constructor TGDIBitmapCanvas.Create(ABitmap: HBITMAP; AWidth, AHeight: Integer);
+begin
+ ASSERT(ABitmap <> 0);
+ FBitmap := ABitmap;
+ inherited Create(Windows.CreateCompatibleDC(0));
+ FWidth := AWidth;
+ FHeight := AHeight;
+ FOldBitmap := Windows.SelectObject(Handle, Bitmap);
+end;
+
+
+destructor TGDIBitmapCanvas.Destroy;
+begin
+ Windows.SelectObject(Handle, FOldBitmap);
+ Windows.DeleteObject(Bitmap);
+ Windows.DeleteDC(Handle);
+ inherited Destroy;
+end;
+
+
+{ TGDIImage }
+
+constructor TGDIImage.Create(AWidth, AHeight: Integer; APixelFormat: TGfxPixelFormat);
+var
+ BitmapInfo: PBitmapInfo;
+ Color: PRGBQUAD;
+ TempDC: HDC;
+begin
+ inherited Create(AWidth, AHeight, APixelFormat);
+
+ case APixelFormat.FormatType of
+ ftMono:
+ begin
+ FStride := (AWidth + 7) shr 3;
+ GetMem(BitmapInfo, SizeOf(TBitmapInfoHeader) + 2 * SizeOf(RGBQUAD));
+ BitmapInfo^.bmiHeader.biClrUsed := 2;
+ Color := @BitmapInfo^.bmiColors[0];
+ Color^.rgbRed := 0;
+ Color^.rgbGreen := 0;
+ Color^.rgbBlue := 0;
+ Color^.rgbReserved := 0;
+ Inc(Color);
+ Color^.rgbRed := 255;
+ Color^.rgbGreen := 255;
+ Color^.rgbBlue := 255;
+ Color^.rgbReserved := 0;
+ end;
+ ftPal4, ftPal4A:
+ begin
+ FStride := (AWidth + 1) shr 1;
+ GetMem(BitmapInfo, SizeOf(TBitmapInfoHeader) + 16 * SizeOf(RGBQUAD));
+ BitmapInfo^.bmiHeader.biClrUsed := 0;
+ end;
+ ftPal8, ftPal8A:
+ begin
+ FStride := AWidth;
+ GetMem(BitmapInfo, SizeOf(TBitmapInfoHeader) + 256 * SizeOf(RGBQUAD));
+ BitmapInfo^.bmiHeader.biClrUsed := 0;
+ end;
+ else
+ begin
+ FStride := AWidth * (FormatTypeBPPTable[APixelFormat.FormatType] shr 3);
+ GetMem(BitmapInfo, SizeOf(TBitmapInfoHeader));
+ BitmapInfo^.bmiHeader.biClrUsed := 0;
+ end;
+ end;
+ // The stride is always a multiple of 4
+ FStride := (FStride + 3) and not 3;
+
+ with BitmapInfo^.bmiHeader do
+ begin
+ biSize := SizeOf(TBitmapInfoHeader);
+ biWidth := AWidth;
+ biHeight := AHeight;
+ biPlanes := 1;
+ biBitCount := FormatTypeBPPTable[APixelFormat.FormatType];
+ biCompression := 0;
+ biSizeImage := 4 * AHeight * AWidth;
+ biXPelsPerMeter := 0;
+ biYPelsPerMeter := 0;
+ biClrImportant := 0;
+ end;
+
+ FData := nil;
+
+ TempDC := GetDC(0);
+ FHandle := Windows.CreateDIBSection(TempDC, BitmapInfo^, DIB_RGB_COLORS, FData, 0, 0);
+ ReleaseDC(0, TempDC);
+
+ FreeMem(BitmapInfo);
+end;
+
+
+destructor TGDIImage.Destroy;
+begin
+ if Handle <> 0 then
+ Windows.DeleteObject(Handle);
+ inherited Destroy;
+end;
+
+
+procedure TGDIImage.Lock(var AData: Pointer; var AStride: LongWord);
+begin
+ ASSERT(not IsLocked);
+ IsLocked := True;
+ AData := Data;
+ AStride := Stride;
+ Windows.GdiFlush;
+end;
+
+procedure TGDIImage.Unlock;
+begin
+ ASSERT(IsLocked);
+ IsLocked := False;
+end;
+
+
+{ TGDIScreen }
+
+constructor TGDIScreen.Create;
+begin
+ inherited Create;
+
+end;
+
+{ TGDIApplication }
+
+constructor TGDIApplication.Create;
+begin
+ inherited Create;
+
+end;
+
+
+destructor TGDIApplication.Destroy;
+var
+ i: Integer;
+begin
+ for i := 0 to Forms.Count - 1 do
+ TGDIWindow(Forms[i]).Free;
+
+ inherited Destroy;
+end;
+
+procedure TGDIApplication.AddWindow(AWindow: TFCustomWindow);
+begin
+ Forms.Add(AWindow);
+end;
+
+
+procedure TGDIApplication.Initialize(ADisplayName: String);
+begin
+
+end;
+
+procedure TGDIApplication.Run;
+var
+ Msg: TMsg;
+begin
+ DoBreakRun := False;
+
+ while Windows.GetMessage(@Msg, 0, 0, 0) and
+ (not (QuitWhenLastWindowCloses and (Forms.Count = 0))) and
+ (DoBreakRun = False) do
+ begin
+ Windows.TranslateMessage(@msg);
+ Windows.DispatchMessage(@msg);
+ end;
+
+ DoBreakRun := False;
+end;
+
+
+procedure TGDIApplication.Quit;
+begin
+ DoBreakRun := True;
+end;
+
+
+{ TGDIWindow }
+
+function fpGFXWindowProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM;
+ lParam: LPARAM): LRESULT; stdcall;
+var
+ Window: TGDIWindow;
+ Msg: TMessage;
+begin
+ if uMsg = WM_CREATE then
+ begin
+ Window := TGDIWindow(PCreateStruct(lParam)^.lpCreateParams);
+ Window.FHandle := hwnd;
+ Windows.SetWindowLong(hwnd, GWL_USERDATA, LongWord(Window));
+ end else
+ Window := TGDIWindow(Windows.GetWindowLong(hwnd, GWL_USERDATA));
+
+ if Assigned(Window) then
+ begin
+ Msg.msg := uMsg;
+ Msg.wParam := wParam;
+ Msg.lParam := lParam;
+ Msg.Result := 0;
+ Window.Dispatch(Msg);
+ Result := Msg.Result;
+ end
+ else
+ if UnicodeEnabledOS then Result := Windows.DefWindowProcW(hwnd, uMsg, wParam, lParam)
+ else Result := Windows.DefWindowProc(hwnd, uMsg, wParam, lParam);
+end;
+
+
+constructor TGDIWindow.Create(AParent: TFCustomWindow; AWindowOptions: TGfxWindowOptions);
+var
+ ParentHandle: HWND;
+begin
+ inherited Create;
+
+ FWindowOptions := AWindowOptions;
+ FParent := AParent;
+
+ { Initialize a window class, if necessary }
+ if UnicodeEnabledOS then
+ begin
+ if not Assigned(WindowClassW.lpfnWndProc) then
+ begin
+ WindowClassW.style := CS_HREDRAW or CS_VREDRAW;
+ WindowClassW.lpfnWndProc := WndProc(@fpGFXWindowProc);
+ WindowClassW.hInstance := MainInstance;
+ WindowClassW.hIcon := LoadIcon(0, IDI_APPLICATION);
+ WindowClassW.hCursor := LoadCursor(0, IDC_ARROW);
+ WindowClassW.hbrBackground := 0;
+ WindowClassW.lpszClassName := 'fpGFX';
+ end;
+ Windows.RegisterClassW(@WindowClassW);
+ end
+ else
+ begin
+ if not Assigned(WindowClass.lpfnWndProc) then
+ begin
+ WindowClass.style := CS_HREDRAW or CS_VREDRAW;
+ WindowClass.lpfnWndProc := WndProc(@fpGFXWindowProc);
+ WindowClass.hInstance := MainInstance;
+ WindowClass.hIcon := LoadIcon(0, IDI_APPLICATION);
+ WindowClass.hCursor := LoadCursor(0, IDC_ARROW);
+ WindowClass.hbrBackground := 0;
+ WindowClass.lpszClassName := 'fpGFX';
+ end;
+ Windows.RegisterClass(@WindowClass);
+ end;
+
+ if Assigned(AParent) then
+ ParentHandle := AParent.Handle
+ else
+ ParentHandle := 0;
+
+ if (woBorderless in FWindowOptions) and (woPopUp in FWindowOptions) then FWindowStyle := WS_POPUP
+ else if woPopUp in FWindowOptions then FWindowStyle := WS_POPUPWINDOW
+ else if woToolWindow in FWindowOptions then FWindowStyle := WS_OVERLAPPED
+ else if woChildWindow in FWindowOptions then FWindowStyle := WS_CHILDWINDOW
+ else if woBorderless in FWindowOptions then FWindowStyle := WS_OVERLAPPED
+ else if woWindow in FWindowOptions then FWindowStyle := WS_OVERLAPPEDWINDOW
+ else FWindowStyle := 0;
+
+ if woPopUp in FWindowOptions then FWindowStyleEx := WS_EX_TOOLWINDOW
+ else if woToolWindow in FWindowOptions then FWindowStyleEx := WS_EX_TOOLWINDOW
+ else if woWindow in FWindowOptions then FWindowStyleEx := WS_EX_APPWINDOW
+ else FWindowStyleEx := 0;
+
+ if UnicodeEnabledOS then
+ FHandle := Windows.CreateWindowExW(
+ FWindowStyleEx, // extended window style
+ 'fpGFX', // registered class name
+ 'fpGFX Window', // window name
+ FWindowStyle, // window style
+ CW_USEDEFAULT, // horizontal position of window
+ CW_USEDEFAULT, // vertical position of window
+ CW_USEDEFAULT, // window width
+ CW_USEDEFAULT, // window height
+ ParentHandle, // handle to parent or owner window
+ 0, // menu handle or child identifier
+ MainInstance, // handle to application instance
+ Self) // window-creation data
+ else
+ FHandle := Windows.CreateWindowEx(
+ FWindowStyleEx, // extended window style
+ 'fpGFX', // registered class name
+ 'fpGFX Window', // window name
+ FWindowStyle, // window style
+ CW_USEDEFAULT, // horizontal position of window
+ CW_USEDEFAULT, // vertical position of window
+ CW_USEDEFAULT, // window width
+ CW_USEDEFAULT, // window height
+ ParentHandle, // handle to parent or owner window
+ 0, // menu handle or child identifier
+ MainInstance, // handle to application instance
+ Self); // window-creation data
+
+ FCanvas := TGDIWindowCanvas.Create(Handle);
+end;
+
+
+destructor TGDIWindow.Destroy;
+var
+ OldHandle: HWND;
+begin
+ if Assigned(OnClose) then
+ OnClose(Self);
+
+ Canvas.Free;
+
+ if Handle <> 0 then
+ begin
+ OldHandle := Handle;
+ FHandle := 0;
+ Windows.DestroyWindow(OldHandle);
+ end;
+
+ gApplication.Forms.Remove(Self);
+
+ // Are we the last window for our owning display?
+ if gApplication.Forms.Count = 0 then
+ Windows.PostQuitMessage(0);
+
+ inherited Destroy;
+end;
+
+
+procedure TGDIWindow.DefaultHandler(var Message);
+begin
+ if UnicodeEnabledOS then
+ TMessage(Message).Result := Windows.DefWindowProcW(Handle,
+ TMessage(Message).Msg, TMessage(Message).wParam, TMessage(Message).lParam)
+ else
+ TMessage(Message).Result := Windows.DefWindowProc(Handle,
+ TMessage(Message).Msg, TMessage(Message).wParam, TMessage(Message).lParam)
+end;
+
+
+procedure TGDIWindow.SetPosition(const APosition: TPoint);
+begin
+ Windows.SetWindowPos(Handle, 0, APosition.x, APosition.y, 0, 0,
+ SWP_NOSIZE or SWP_NOZORDER);
+end;
+
+
+procedure TGDIWindow.SetSize(const ASize: TSize);
+begin
+ if (ASize.cx <> Width) or (ASize.cy <> Height) then
+ Windows.SetWindowPos(Handle, 0, 0, 0, ASize.cx, ASize.cy,
+ SWP_NOMOVE or SWP_NOZORDER);
+end;
+
+
+procedure TGDIWindow.SetMinMaxSize(const AMinSize, AMaxSize: TSize);
+begin
+ FMinSize := AMinSize;
+ FMaxSize := AMaxSize;
+ UpdateWindowButtons;
+end;
+
+
+procedure TGDIWindow.SetClientSize(const ASize: TSize);
+var
+ r: Windows.Rect;
+begin
+ if (ASize.cx <> ClientWidth) or (ASize.cx <> ClientHeight) then
+ begin
+ r.Left := 0;
+ r.Top := 0;
+ r.Right := ASize.cx;
+ r.Bottom := ASize.cy;
+ Windows.AdjustWindowRectEx(r, FWindowStyle, False, FWindowStyleEx);
+ SetSize(Size(WinRectToRect(r)));
+ end;
+end;
+
+
+procedure TGDIWindow.SetMinMaxClientSize(const AMinSize, AMaxSize: TSize);
+var
+ Rect: Windows.Rect;
+begin
+ Rect.Left := 0;
+ Rect.Top := 0;
+ Rect.Right := AMinSize.cx;
+ Rect.Bottom := AMinSize.cy;
+ Windows.AdjustWindowRectEx(Rect, FWindowStyle, False, FWindowStyleEx);
+ if AMinSize.cx > 0 then
+ FMinSize.cx := Rect.Right - Rect.Left
+ else
+ FMinSize.cx := 0;
+ if AMinSize.cy > 0 then
+ FMinSize.cy := Rect.Bottom - Rect.Top
+ else
+ FMinSize.cy := 0;
+
+ Rect.Left := 0;
+ Rect.Top := 0;
+ Rect.Right := AMaxSize.cx;
+ Rect.Bottom := AMaxSize.cy;
+ Windows.AdjustWindowRectEx(Rect, FWindowStyle, False, FWindowStyleEx);
+ if AMaxSize.cx > 0 then
+ FMaxSize.cx := Rect.Right - Rect.Left
+ else
+ FMaxSize.cx := 0;
+ if AMaxSize.cy > 0 then
+ FMaxSize.cy := Rect.Bottom - Rect.Top
+ else
+ FMaxSize.cy := 0;
+
+ UpdateWindowButtons;
+end;
+
+
+procedure TGDIWindow.Show;
+begin
+ Windows.ShowWindow(Handle, SW_SHOWNORMAL);
+ Windows.UpdateWindow(Handle);
+end;
+
+
+procedure TGDIWindow.Invalidate(const ARect: TRect);
+var
+ Rect: Windows.Rect;
+begin
+ Rect.Left := ARect.Left;
+ Rect.Top := ARect.Top;
+ Rect.Right := ARect.Right;
+ Rect.Bottom := ARect.Bottom;
+ Windows.InvalidateRect(Handle, Rect, False);
+end;
+
+
+procedure TGDIWindow.PaintInvalidRegion;
+begin
+ Windows.UpdateWindow(Handle);
+end;
+
+
+procedure TGDIWindow.CaptureMouse;
+begin
+ if FHasMouseCapture then
+ exit;
+
+ FHasMouseCapture := True;
+
+ if not FMouseInWindow then
+ begin
+ FMouseInWindow := True;
+ Windows.SetCapture(Handle);
+ end;
+end;
+
+
+procedure TGDIWindow.ReleaseMouse;
+begin
+ if FHasMouseCapture then
+ begin
+ FHasMouseCapture := False;
+ if not FMouseInWindow then
+ begin
+ Windows.ReleaseCapture;
+ end;
+ end;
+end;
+
+
+function TGDIWindow.GetTitle: String;
+var
+ TextLen: Integer;
+ AnsiBuffer: string;
+ WideBuffer: WideString;
+begin
+ if UnicodeEnabledOS then
+ begin
+ TextLen := Windows.GetWindowTextLengthW(Handle);
+ SetLength(WideBuffer, TextLen);
+ TextLen := Windows.GetWindowTextW(Handle, @WideBuffer[1], TextLen + 1);
+ SetLength(WideBuffer, TextLen);
+ Result := Utf8Encode(WideBuffer);
+ end
+ else
+ begin
+ TextLen := Windows.GetWindowTextLength(Handle);
+ SetLength(AnsiBuffer, TextLen);
+ TextLen := Windows.GetWindowText(Handle, @AnsiBuffer[1], TextLen + 1);
+ SetLength(AnsiBuffer, TextLen);
+ Result := AnsiToUtf8(AnsiBuffer);
+ end;
+end;
+
+procedure TGDIWindow.SetTitle(const ATitle: String);
+begin
+ if UnicodeEnabledOS then
+ Windows.SetWindowTextW(Handle, PWideChar(Utf8Decode(ATitle)))
+ else Windows.SetWindowText(Handle, PChar(Utf8ToAnsi(ATitle)));
+end;
+
+
+procedure TGDIWindow.DoSetCursor;
+const
+ CursorTable: array[TGfxCursor] of Integer = (
+ 32512, // crDefault
+ 0, // crNone
+ 32512, // crArrow
+ 32515, // crCross
+ 32513, // crIBeam
+ 32646, // crSize
+ 32645, // crSizeNS
+ 32644, // crSizeWE
+ 32516, // crUpArrow
+ 32514, // crHourGlass
+ 32648, // crNoDrop
+ 32651); // crHelp
+var
+ ID: Integer;
+begin
+ if FMouseInWindow then
+ begin
+ ID := CursorTable[Cursor];
+ if ID <> 0 then
+ Windows.SetCursor(Windows.LoadCursor(0, MAKEINTRESOURCE(ID)))
+ else
+ Windows.SetCursor(0);
+ end;
+end;
+
+
+procedure TGDIWindow.UpdateWindowButtons;
+var
+ CanMaximize: Boolean;
+begin
+ if woWindow in FWindowOptions then
+ begin
+ CanMaximize := (FMaxSize.cx = 0) or (FMaxSize.cy = 0) or
+ (FMaxSize.cx > FMinSize.cx) or (FMaxSize.cy > FMinSize.cy);
+
+ if CanMaximize and ((FWindowStyle and WS_MAXIMIZEBOX) = 0) then
+ FWindowStyle := FWindowStyle or WS_MAXIMIZEBOX
+ else if (not CanMaximize) and
+ ((FWindowStyle and WS_MAXIMIZEBOX) <> 0) then
+ FWindowStyle := FWindowStyle and not WS_MAXIMIZEBOX;
+
+ Windows.SetWindowLong(Handle, GWL_STYLE, FWindowStyle or
+ (Windows.GetWindowLong(Handle, GWL_STYLE) and
+ (WS_MAXIMIZE or WS_MINIMIZE or WS_VISIBLE))); // preserver these bits!
+ end;
+end;
+
+
+function WindowFromPoint(x, y: Windows.LONG):Windows.HWND; external 'user32' name 'WindowFromPoint';
+
+
+function TGDIWindow.DoMouseEnterLeaveCheck(const Msg: TMessage): Boolean;
+
+ function CursorInDifferentWindow: Boolean;
+ var
+ pt: Windows.POINT;
+ begin
+ pt.x := Msg.lParamLo;
+ pt.y := Msg.lParamHi;
+
+ // only WM_MOUSEWHEEL uses screen coordinates!!!
+ if Msg.Msg <> WM_MOUSEWHEEL then
+ Windows.ClientToScreen(Handle, pt);
+
+ Result := WindowFromPoint(pt.x, pt.y) <> Handle;
+{!!!: Result := Windows.WindowFromPoint(pt) <> Handle;}
+ end;
+
+var
+ pt: Windows.POINT;
+begin
+ if not FMouseInWindow then
+ begin
+ FMouseInWindow := True;
+ DoSetCursor;
+ Windows.SetCapture(Handle);
+ if Assigned(OnMouseEnter) then
+ OnMouseEnter(Self, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+ Result := Msg.Msg <> WM_MOUSEMOVE;
+ end else
+ begin
+ pt.x := Msg.lParamLo;
+ pt.y := Msg.lParamHi;
+ if Msg.Msg = WM_MOUSEWHEEL then
+ Windows.ScreenToClient(Handle, pt);
+ if (pt.x < 0) or (pt.y < 0) or (pt.x >= ClientWidth) or
+ (pt.y >= ClientHeight) or CursorInDifferentWindow then
+ FMouseInWindow := False;
+
+ if (not FHasMouseCapture) and (not FMouseInWindow) then
+ begin
+ Windows.ReleaseCapture;
+ if Assigned(OnMouseLeave) then
+ OnMouseLeave(Self);
+ Result := False;
+ end else
+ Result := True;
+ end;
+end;
+
+
+// private methods
+
+procedure TGDIWindow.WMCreate(var Msg: TMessage);
+begin
+ if Assigned(OnCreate) then
+ OnCreate(Self);
+end;
+
+
+procedure TGDIWindow.WMDestroy(var Msg: TMessage);
+begin
+ if Handle <> 0 then
+ Self.Free;
+end;
+
+
+procedure TGDIWindow.WMGetMinMaxInfo(var Msg: TMessage);
+begin
+ with PMinMaxInfo(Msg.lParam)^ do
+ begin
+ if FMinSize.cx > 0 then
+ ptMinTrackSize.x := FMinSize.cx;
+ if FMinSize.cy > 0 then
+ ptMinTrackSize.y := FMinSize.cy;
+ if FMaxSize.cx > 0 then
+ ptMaxTrackSize.x := FMaxSize.cx;
+ if FMaxSize.cy > 0 then
+ ptMaxTrackSize.y := FMaxSize.cy;
+ end;
+end;
+
+
+procedure TGDIWindow.WMActivate(var Msg: TMessage);
+begin
+ if Msg.wParam = WA_INACTIVE then
+ begin
+ FHasFocus := False;
+ if Assigned(OnFocusOut) then
+ OnFocusOut(Self);
+ end else
+ begin
+ FHasFocus := True;
+ if Assigned(OnFocusIn) then
+ OnFocusIn(Self);
+ end;
+end;
+
+
+procedure TGDIWindow.WMPaint(var Msg: TMessage);
+var
+ PaintStruct: TPaintStruct;
+ r: TRect;
+ OldCanvas: TFCustomCanvas;
+begin
+ Windows.BeginPaint(Handle, @PaintStruct);
+ if Assigned(OnPaint) then
+ begin
+ with PaintStruct.rcPaint do
+ begin
+ r.Left := Left;
+ r.Top := Top;
+ r.Right := Right;
+ r.Bottom := Bottom;
+ end;
+ OldCanvas := Canvas;
+ FCanvas := TGDICanvas.Create(PaintStruct.hdc);
+ OnPaint(Self, r);
+ Canvas.Free;
+ FCanvas := OldCanvas;
+ end;
+ Windows.EndPaint(Handle, @PaintStruct);
+end;
+
+
+procedure TGDIWindow.WMShowWindow(var Msg: TMessage);
+begin
+ if Msg.wParam <> 0 then
+ begin
+ if Assigned(OnFocusIn) then
+ OnFocusIn(Self);
+ if Assigned(OnShow) then
+ OnShow(Self);
+ end else
+ if Assigned(OnHide) then
+ OnHide(Self);
+end;
+
+
+procedure TGDIWindow.WMMove(var Msg: TMessage);
+begin
+ if (Msg.lParamLo <> Left) or (Msg.lParamHi <> Top) then
+ begin
+ FLeft := Msg.lParamLo;
+ FTop := Msg.lParamHi;
+ if Assigned(OnMove) then
+ OnMove(Self);
+ end;
+end;
+
+
+procedure TGDIWindow.WMSize(var Msg: TMessage);
+var
+ r: Windows.Rect;
+begin
+ if (Msg.lParamLo <> ClientWidth) or (Msg.lParamHi <> ClientHeight) then
+ begin
+ Windows.GetWindowRect(Handle, r);
+ FWidth := r.Right - r.Left;
+ FHeight := r.Bottom - r.Top;
+ Windows.GetClientRect(Handle, r);
+ FClientWidth := Msg.lParamLo;
+ FClientHeight := Msg.lParamHi;
+ TGDICanvas(Canvas).Resized(FWidth, FHeight);
+ if Assigned(OnResize) then
+ OnResize(Self);
+ end;
+end;
+
+
+procedure TGDIWindow.WMLButtonDown(var Msg: TMessage);
+begin
+ if FMouseInWindow and not FHasFocus then
+ Windows.SetActiveWindow(Handle);
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMousePressed) then
+ OnMousePressed(Self, mbLeft, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+
+procedure TGDIWindow.WMLButtonUp(var Msg: TMessage);
+begin
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMouseReleased) then
+ OnMouseReleased(Self, mbLeft, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+
+procedure TGDIWindow.WMRButtonDown(var Msg: TMessage);
+begin
+ if FMouseInWindow and not FHasFocus then
+ Windows.SetActiveWindow(Handle);
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMousePressed) then
+ OnMousePressed(Self, mbRight, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+
+procedure TGDIWindow.WMRButtonUp(var Msg: TMessage);
+begin
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMouseReleased) then
+ OnMouseReleased(Self, mbRight, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+
+procedure TGDIWindow.WMMButtonDown(var Msg: TMessage);
+begin
+ if FMouseInWindow and not FHasFocus then
+ Windows.SetActiveWindow(Handle);
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMousePressed) then
+ OnMousePressed(Self, mbMiddle, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+procedure TGDIWindow.WMMButtonUp(var Msg: TMessage);
+begin
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMouseReleased) then
+ OnMouseReleased(Self, mbMiddle, GetKeyboardShiftState,
+ Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+procedure TGDIWindow.WMMouseMove(var Msg: TMessage);
+begin
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMouseMove) then
+ OnMouseMove(Self, GetKeyboardShiftState, Point(Msg.lParamLo, Msg.lParamHi));
+end;
+
+procedure TGDIWindow.WMMouseWheel(var Msg: TMessage);
+var
+ pt: Windows.POINT;
+begin
+ if DoMouseEnterLeaveCheck(Msg) and Assigned(OnMouseWheel) then
+ begin
+ pt.x := Msg.lParamLo;
+ pt.y := Msg.lParamHi;
+ Windows.ScreenToClient(Handle, pt);
+ OnMouseWheel(Self, GetKeyboardShiftState, SmallInt(Msg.wParamHi) / -120.0,
+ Point(pt.x, pt.y));
+ end;
+end;
+
+procedure TGDIWindow.WMKeyDown(var Msg: TMessage);
+begin
+ if Assigned(OnKeyPressed) then
+ OnKeyPressed(Self, VirtKeyToKeycode(Msg.wParam), GetKeyboardShiftState);
+ if (Msg.wParam = $2e {VK_DELETE}) and Assigned(OnKeyChar) then
+ OnKeyChar(Self, #127);
+end;
+
+procedure TGDIWindow.WMKeyUp(var Msg: TMessage);
+begin
+ if Assigned(OnKeyReleased) then
+ OnKeyReleased(Self, VirtKeyToKeycode(Msg.wParam), GetKeyboardShiftState);
+end;
+
+procedure TGDIWindow.WMChar(var Msg: TMessage);
+begin
+ if Assigned(OnKeyChar) then
+ OnKeyChar(Self, Chr(Msg.wParam));
+end;
+
+procedure TGDIWindow.WMSysKeyDown(var Msg: TMessage);
+begin
+ WMKeyDown(Msg);
+end;
+
+procedure TGDIWindow.WMSysKeyUp(var Msg: TMessage);
+begin
+ WMKeyUp(Msg);
+end;
+
+procedure TGDIWindow.WMSysChar(var Msg: TMessage);
+begin
+ WMChar(Msg);
+end;
+
+
+{ Helpers }
+
+function RectToWinRect(const ARect: TRect): Windows.Rect;
+begin
+ Result.Left := ARect.Left;
+ Result.Top := ARect.Top;
+ Result.Right := ARect.Right;
+ Result.Bottom := ARect.Bottom;
+end;
+
+function WinRectToRect(const ARect: Windows.Rect): TRect;
+begin
+ Result.Left := ARect.Left;
+ Result.Top := ARect.Top;
+ Result.Right := ARect.Right;
+ Result.Bottom := ARect.Bottom;
+end;
+
+
+{$INCLUDE gdikeys.inc}
+
+initialization
+
+ WinVersion.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
+ GetVersionEx(WinVersion);
+
+ UnicodeEnabledOS := (WinVersion.dwPlatformID = VER_PLATFORM_WIN32_NT)
+ or (WinVersion.dwPlatformID = VER_PLATFORM_WIN32_CE);
+
+end.
+
diff --git a/gfx/gdi/gfxinterface.pas b/gfx/gdi/gfxinterface.pas
new file mode 100644
index 00000000..976160b7
--- /dev/null
+++ b/gfx/gdi/gfxinterface.pas
@@ -0,0 +1,39 @@
+{
+ fpGUI - Free Pascal GUI Library
+
+ GFXInterface - Default target selection unit for Windows GDI target
+
+ Copyright (C) 2000 - 2006 See the file AUTHORS, included in this
+ distribution, for details of the copyright.
+
+ See the file COPYING.modifiedLGPL, included in this distribution,
+ for details about redistributing fpGUI.
+
+ This program 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.
+}
+unit GFXInterface;
+
+interface
+
+uses GFX_GDI;
+
+type
+
+ TDefFont = TGDIFont;
+
+ TDefCanvas = TGDICanvas;
+
+ TDefImage = TGDIImage;
+
+ TDefScreen = TGDIScreen;
+
+ TDefApplication = TGDIApplication;
+
+ TDefWindow = TGDIWindow;
+
+implementation
+
+end.
+