diff options
author | Graeme Geldenhuys <graemeg@users.sourceforge.net> | 2006-11-18 18:11:20 +0000 |
---|---|---|
committer | Graeme Geldenhuys <graemeg@users.sourceforge.net> | 2006-11-18 18:11:20 +0000 |
commit | 8fe7ea95a343a35dc286bd9a13d257d285e9c4e1 (patch) | |
tree | ea9f9317f46f4c320a2667e0e0d4362c4f0980a3 /gfx/gdi | |
parent | 546dce65494ea4e5f654e2840cc67307101e06f7 (diff) | |
download | fpGUI-8fe7ea95a343a35dc286bd9a13d257d285e9c4e1.tar.xz |
Initial checkin. Merged fpGUI, fpGFX and fpIMG from the OpenSoft sever.
Diffstat (limited to 'gfx/gdi')
-rw-r--r-- | gfx/gdi/Makefile | 1249 | ||||
-rw-r--r-- | gfx/gdi/Makefile.fpc | 36 | ||||
-rw-r--r-- | gfx/gdi/fpgfxpackage.lpk | 68 | ||||
-rw-r--r-- | gfx/gdi/fpgfxpackage.pas | 14 | ||||
-rw-r--r-- | gfx/gdi/gdikeys.inc | 330 | ||||
-rw-r--r-- | gfx/gdi/gfx_gdi.pas | 1730 | ||||
-rw-r--r-- | gfx/gdi/gfxinterface.pas | 39 |
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. + |