add oversampler

This commit is contained in:
2024-05-24 13:28:31 +02:00
parent e4a4a661a0
commit 989dba5a6b
484 changed files with 313937 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# use make
# or make NOGDK=1
# or make DEBUG=1
# etc
ARCH := $(shell uname -m)
UNAME_S := $(shell uname -s)
ifeq ($(ARCH), aarch64)
ifeq ($(shell $(CC) -dumpmachine | cut -f 1 -d -), arm)
# helper for armv7l userspace on aarch64 cpu
ARCH := armv7l
endif
endif
PKG_CONFIG = pkg-config
COMPILER=GCC
CFLAGS = -pipe -fvisibility=hidden -fno-math-errno -fPIC -DPIC -Wall -Wshadow -Wno-unused-function -Wno-multichar -Wtype-limits
CFLAGS += -DSWELL_MAKING_DYLIB
ifeq ($(UNAME_S),Darwin)
CFLAGS += -Wno-unused-private-field -DSWELL_FORCE_GENERIC
DLL_EXT=.dylib
COMPILER=CLANG
else
DLL_EXT=.so
CFLAGS += -D_FILE_OFFSET_BITS=64
endif
ifeq ($(COMPILER),CLANG)
CC = clang
CXX = clang++
endif
ifeq ($(COMPILER),ICC)
CC = icc
CXX = icpc
CFLAGS += -D__PURE_SYS_C99_HEADERS__
else
CFLAGS += -Wno-unused-result
endif
ifndef ALLOW_WARNINGS
CFLAGS += -Werror
endif
ifndef DEPRECATED_WARNINGS
CFLAGS += -Wno-deprecated-declarations
endif
ifeq ($(ARCH),arm64)
CFLAGS += -fsigned-char
else
ifneq ($(filter arm%,$(ARCH)),)
CFLAGS += -fsigned-char -marm
endif
ifeq ($(ARCH),aarch64)
CFLAGS += -fsigned-char
endif
endif
ifdef DEBUG
CFLAGS += -O0 -g -D_DEBUG
else
CFLAGS += -O2 -DNDEBUG
ifdef DEBUG_INFO
CFLAGS += -g
else
ifneq ($(COMPILER),CLANG)
CFLAGS += -s
endif
endif
endif
LINKEXTRA = -lpthread -ldl
EXTRA_OBJS =
vpath %.cpp .. ../lice
SWELL_OBJS = swell.o swell-ini.o swell-miscdlg-generic.o swell-wnd-generic.o \
swell-menu-generic.o swell-kb-generic.o swell-dlg-generic.o \
swell-gdi-generic.o swell-misc-generic.o swell-gdi-lice.o \
swell-generic-headless.o swell-generic-gdk.o \
swell-appstub-generic.o swell-modstub-generic.o
LICE_OBJS = lice.o lice_arc.o lice_colorspace.o lice_line.o lice_text.o \
lice_textnew.o lice_ico.o lice_bmp.o
OBJS = $(SWELL_OBJS)
ifndef NOGDK
ifdef GDK2
CFLAGS += -DSWELL_TARGET_GDK=2 $(shell $(PKG_CONFIG) --cflags gdk-2.0)
ifndef PRELOAD_GDK
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gdk-2.0)
else
LINKEXTRA += -lX11 -lXi
CFLAGS += -DSWELL_PRELOAD="libgdk-x11-2.0.so.0"
endif
else
ifdef SWELL_SUPPORT_GTK
CFLAGS += -DSWELL_TARGET_GDK=3 $(shell $(PKG_CONFIG) --cflags gtk+-3.0) -DSWELL_SUPPORT_GTK
else
CFLAGS += -DSWELL_TARGET_GDK=3 $(shell $(PKG_CONFIG) --cflags gdk-3.0)
endif
ifndef PRELOAD_GDK
ifdef SWELL_SUPPORT_GTK
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gtk+-3.0)
else
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gdk-3.0)
endif
else
LINKEXTRA += -lX11 -lXi
ifdef SWELL_SUPPORT_GTK
CFLAGS += -DSWELL_PRELOAD="libgtk+-3.so.0"
else
CFLAGS += -DSWELL_PRELOAD="libgdk-3.so.0"
endif
endif
endif
CFLAGS += -DSWELL_LICE_GDI
OBJS += $(LICE_OBJS)
ifndef NOFREETYPE
CFLAGS += -DSWELL_FREETYPE $(shell $(PKG_CONFIG) --cflags freetype2)
ifndef PRELOAD_GDK
LINKEXTRA += $(shell $(PKG_CONFIG) --libs freetype2)
endif
ifndef NOFONTCONFIG
CFLAGS += -DSWELL_FONTCONFIG
LINKEXTRA += -lfontconfig
endif
endif
LINKEXTRA += -lGL
ifdef PRELOAD_GDK
CFLAGS += -Wl,-z,lazy
endif
endif
CXXFLAGS = $(CFLAGS)
default: libSwell$(DLL_EXT)
.PHONY: clean
SWELL_HEADERS=swell-dlggen.h swell-gdi-internalpool.h swell-menugen.h swell-types.h swell-functions.h swell-internal.h
swell.o: $(SWELL_HEADERS)
swell-ini.o: $(SWELL_HEADERS)
swell-wnd-generic.o: $(SWELL_HEADERS)
swell-dlg-generic.o: $(SWELL_HEADERS)
swell-menu-generic.o: $(SWELL_HEADERS)
swell-misc-generic.o: $(SWELL_HEADERS)
swell-gdi-generic.o: $(SWELL_HEADERS)
swell-gdi-lice.o: $(SWELL_HEADERS)
swell-kb-generic.o: $(SWELL_HEADERS)
swell-miscdlg-generic.o: $(SWELL_HEADERS)
swell-modstub-generic.o: $(SWELL_HEADERS)
swell-appstub-generic.o: $(SWELL_HEADERS)
libSwell$(DLL_EXT): $(OBJS)
$(CXX) -shared -o $@ $(CFLAGS) $(LFLAGS) $^ $(LINKEXTRA)
test: $(OBJS) test.o
$(CXX) -o test $(CFLAGS) $(LFLAGS) $^ $(LINKEXTRA)
libSwell.colortheme: swell-gdi-generic.cpp $(SWELL_HEADERS)
$(CXX) $(CFLAGS) -o make-theme -DSWELL__MAKE_THEME swell-gdi-generic.cpp -lpthread
./make-theme > libSwell.colortheme
clean:
-rm -f -- $(OBJS) libSwell$(DLL_EXT) make-theme libSwell.colortheme

View File

@@ -0,0 +1 @@
#include <windows.h>

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,102 @@
APPNAME=myapp
WDL_PATH = ../WDL
vpath swell%.cpp $(WDL_PATH)/swell
vpath lice%.cpp $(WDL_PATH)/lice
vpath %.c $(WDL_PATH)
vpath %.cpp $(WDL_PATH) $(WDL_PATH)/wingui
###### Objects and resources (probably too many)
SWELL_OBJS = swell.o swell-ini.o swell-miscdlg-generic.o swell-wnd-generic.o \
swell-menu-generic.o swell-kb-generic.o swell-dlg-generic.o \
swell-gdi-generic.o swell-misc-generic.o swell-gdi-lice.o \
swell-generic-gdk.o swell-appstub-generic.o swell-modstub-generic.o
LICE_OBJS = lice_image.o lice_arc.o lice_line.o lice_text.o \
lice_textnew.o lice.o lice_colorspace.o
OTHER_OBJS = wndsize.o
RESFILES = res.rc_mac_dlg res.rc_mac_menu
OBJS += myapp.o $(SWELL_OBJS) $(OTHER_OBJS)
###### Compiler/Linker flags
CFLAGS += -pipe -fvisibility=hidden -fno-math-errno -fPIC -DPIC -Wall -Wshadow -Wtype-limits \
-Wno-unused-function -Wno-multichar -Wno-unused-result
CFLAGS += -D_FILE_OFFSET_BITS=64
ARCH := $(shell uname -m)
PKG_CONFIG = pkg-config
ifndef ALLOW_WARNINGS
CFLAGS += -Werror
endif
ifndef DEPRECATED_WARNINGS
CFLAGS += -Wno-deprecated-declarations
endif
ifneq ($(filter arm%,$(ARCH)),)
CFLAGS += -fsigned-char -marm
endif
ifdef DEBUG
CFLAGS += -O0 -g -D_DEBUG -DWDL_CHECK_FOR_NON_UTF8_FOPEN
else
CFLAGS += -O2 -DNDEBUG
endif
LINKEXTRA = -lpthread -ldl
ifndef NOGDK
ifdef GDK2
CFLAGS += -DSWELL_TARGET_GDK=2 $(shell $(PKG_CONFIG) --cflags gdk-2.0)
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gdk-2.0)
LINKEXTRA += -lX11 -lXi
else
ifdef SWELL_SUPPORT_GTK
CFLAGS += -DSWELL_TARGET_GDK=3 $(shell $(PKG_CONFIG) --cflags gtk+-3.0) -DSWELL_SUPPORT_GTK
else
CFLAGS += -DSWELL_TARGET_GDK=3 $(shell $(PKG_CONFIG) --cflags gdk-3.0)
endif
LINKEXTRA += -lX11 -lXi -lGL
ifdef SWELL_SUPPORT_GTK
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gtk+-3.0)
else
LINKEXTRA += $(shell $(PKG_CONFIG) --libs gdk-3.0)
endif
endif
CFLAGS += -DSWELL_LICE_GDI
OBJS += $(LICE_OBJS)
ifndef NOFREETYPE
CFLAGS += -DSWELL_FREETYPE $(shell $(PKG_CONFIG) --cflags freetype2)
LINKEXTRA += $(shell $(PKG_CONFIG) --libs freetype2)
ifndef NOFONTCONFIG
CFLAGS += -DSWELL_FONTCONFIG
LINKEXTRA += -lfontconfig
endif
endif
endif
CXXFLAGS = $(CFLAGS)
default: $(APPNAME)
.PHONY: clean run
$(RESFILES): res.rc
$(WDL_PATH)/swell/swell_resgen.pl $^
$(APPNAME): $(RESFILES) $(OBJS)
$(CXX) -o $@ $(CFLAGS) $(OBJS) $(LINKEXTRA)
run: $(APPNAME)
./$^
clean:
-rm $(OBJS) $(APPNAME) $(RESFILES)

View File

@@ -0,0 +1,406 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
338536692957A46300048720 /* myapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 338536682957A46300048720 /* myapp.cpp */; };
3385366B2957A4D300048720 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3385366A2957A4D300048720 /* main.m */; };
338536702957A62F00048720 /* MyApp.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3385366E2957A62F00048720 /* MyApp.icns */; };
338536732957A6EB00048720 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 338536712957A6EB00048720 /* MainMenu.xib */; };
3385932D185B555500FDFFEA /* wndsize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3385932C185B555500FDFFEA /* wndsize.cpp */; };
33AA3116185A7E8D001D767E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33AA3115185A7E8D001D767E /* Cocoa.framework */; };
33AA3126185A7E8D001D767E /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 33AA3124185A7E8D001D767E /* Credits.rtf */; };
33F96581185A7F79004C7070 /* swell-appstub.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F96576185A7F79004C7070 /* swell-appstub.mm */; };
33F96582185A7F79004C7070 /* swell-dlg.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F96577185A7F79004C7070 /* swell-dlg.mm */; };
33F96583185A7F79004C7070 /* swell-gdi.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F96578185A7F79004C7070 /* swell-gdi.mm */; };
33F96584185A7F79004C7070 /* swell-ini.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33F96579185A7F79004C7070 /* swell-ini.cpp */; };
33F96585185A7F79004C7070 /* swell-kb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657A185A7F79004C7070 /* swell-kb.mm */; };
33F96586185A7F79004C7070 /* swell-menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657B185A7F79004C7070 /* swell-menu.mm */; };
33F96587185A7F79004C7070 /* swell-misc.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657C185A7F79004C7070 /* swell-misc.mm */; };
33F96588185A7F79004C7070 /* swell-miscdlg.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657D185A7F79004C7070 /* swell-miscdlg.mm */; };
33F96589185A7F79004C7070 /* swell-wnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657E185A7F79004C7070 /* swell-wnd.mm */; };
33F9658A185A7F79004C7070 /* swell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33F9657F185A7F79004C7070 /* swell.cpp */; };
33F9658B185A7F79004C7070 /* swellappmain.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F96580185A7F79004C7070 /* swellappmain.mm */; };
33F9658D185A8228004C7070 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33F9658C185A8228004C7070 /* Carbon.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
338536682957A46300048720 /* myapp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = myapp.cpp; sourceTree = SOURCE_ROOT; };
3385366A2957A4D300048720 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
3385366C2957A62F00048720 /* MyApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MyApp-Info.plist"; sourceTree = SOURCE_ROOT; };
3385366D2957A62F00048720 /* MyApp-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MyApp-Prefix.pch"; sourceTree = SOURCE_ROOT; };
3385366E2957A62F00048720 /* MyApp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = MyApp.icns; sourceTree = SOURCE_ROOT; };
338536722957A6EB00048720 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
3385932C185B555500FDFFEA /* wndsize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = wndsize.cpp; path = ../WDL/wingui/wndsize.cpp; sourceTree = "<group>"; };
33AA3112185A7E8D001D767E /* MyApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
33AA3115185A7E8D001D767E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
33AA3118185A7E8D001D767E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
33AA3119185A7E8D001D767E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
33AA311A185A7E8D001D767E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
33AA311F185A7E8D001D767E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
33AA3125185A7E8D001D767E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
33F96576185A7F79004C7070 /* swell-appstub.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-appstub.mm"; path = "../WDL/swell/swell-appstub.mm"; sourceTree = "<group>"; };
33F96577185A7F79004C7070 /* swell-dlg.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-dlg.mm"; path = "../WDL/swell/swell-dlg.mm"; sourceTree = "<group>"; };
33F96578185A7F79004C7070 /* swell-gdi.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-gdi.mm"; path = "../WDL/swell/swell-gdi.mm"; sourceTree = "<group>"; };
33F96579185A7F79004C7070 /* swell-ini.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "swell-ini.cpp"; path = "../WDL/swell/swell-ini.cpp"; sourceTree = "<group>"; };
33F9657A185A7F79004C7070 /* swell-kb.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-kb.mm"; path = "../WDL/swell/swell-kb.mm"; sourceTree = "<group>"; };
33F9657B185A7F79004C7070 /* swell-menu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-menu.mm"; path = "../WDL/swell/swell-menu.mm"; sourceTree = "<group>"; };
33F9657C185A7F79004C7070 /* swell-misc.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-misc.mm"; path = "../WDL/swell/swell-misc.mm"; sourceTree = "<group>"; };
33F9657D185A7F79004C7070 /* swell-miscdlg.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-miscdlg.mm"; path = "../WDL/swell/swell-miscdlg.mm"; sourceTree = "<group>"; };
33F9657E185A7F79004C7070 /* swell-wnd.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "swell-wnd.mm"; path = "../WDL/swell/swell-wnd.mm"; sourceTree = "<group>"; };
33F9657F185A7F79004C7070 /* swell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = swell.cpp; path = ../WDL/swell/swell.cpp; sourceTree = "<group>"; };
33F96580185A7F79004C7070 /* swellappmain.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = swellappmain.mm; path = ../WDL/swell/swellappmain.mm; sourceTree = "<group>"; };
33F9658C185A8228004C7070 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
33AA310F185A7E8D001D767E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
33F9658D185A8228004C7070 /* Carbon.framework in Frameworks */,
33AA3116185A7E8D001D767E /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
33AA3109185A7E8D001D767E = {
isa = PBXGroup;
children = (
338536712957A6EB00048720 /* MainMenu.xib */,
338536682957A46300048720 /* myapp.cpp */,
3385366C2957A62F00048720 /* MyApp-Info.plist */,
3385366D2957A62F00048720 /* MyApp-Prefix.pch */,
3385366E2957A62F00048720 /* MyApp.icns */,
3385366A2957A4D300048720 /* main.m */,
33AA3149185A7EEC001D767E /* WDL */,
33AA311E185A7E8D001D767E /* InfoPlist.strings */,
33AA3124185A7E8D001D767E /* Credits.rtf */,
33AA3114185A7E8D001D767E /* Frameworks */,
33AA3113185A7E8D001D767E /* Products */,
);
sourceTree = "<group>";
};
33AA3113185A7E8D001D767E /* Products */ = {
isa = PBXGroup;
children = (
33AA3112185A7E8D001D767E /* MyApp.app */,
);
name = Products;
sourceTree = "<group>";
};
33AA3114185A7E8D001D767E /* Frameworks */ = {
isa = PBXGroup;
children = (
33F9658C185A8228004C7070 /* Carbon.framework */,
33AA3115185A7E8D001D767E /* Cocoa.framework */,
33AA3117185A7E8D001D767E /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
33AA3117185A7E8D001D767E /* Other Frameworks */ = {
isa = PBXGroup;
children = (
33AA3118185A7E8D001D767E /* AppKit.framework */,
33AA3119185A7E8D001D767E /* CoreData.framework */,
33AA311A185A7E8D001D767E /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
33AA3149185A7EEC001D767E /* WDL */ = {
isa = PBXGroup;
children = (
3385932C185B555500FDFFEA /* wndsize.cpp */,
33AA314A185A7EF4001D767E /* swell */,
);
name = WDL;
path = ../WDL;
sourceTree = "<group>";
};
33AA314A185A7EF4001D767E /* swell */ = {
isa = PBXGroup;
children = (
33F96576185A7F79004C7070 /* swell-appstub.mm */,
33F96577185A7F79004C7070 /* swell-dlg.mm */,
33F96578185A7F79004C7070 /* swell-gdi.mm */,
33F96579185A7F79004C7070 /* swell-ini.cpp */,
33F9657A185A7F79004C7070 /* swell-kb.mm */,
33F9657B185A7F79004C7070 /* swell-menu.mm */,
33F9657C185A7F79004C7070 /* swell-misc.mm */,
33F9657D185A7F79004C7070 /* swell-miscdlg.mm */,
33F9657E185A7F79004C7070 /* swell-wnd.mm */,
33F9657F185A7F79004C7070 /* swell.cpp */,
33F96580185A7F79004C7070 /* swellappmain.mm */,
);
name = swell;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
33AA3111185A7E8D001D767E /* MyApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 33AA3143185A7E8D001D767E /* Build configuration list for PBXNativeTarget "MyApp" */;
buildPhases = (
3304E16F1FC2253B00290319 /* ShellScript */,
33AA310E185A7E8D001D767E /* Sources */,
33AA310F185A7E8D001D767E /* Frameworks */,
33AA3110185A7E8D001D767E /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = MyApp;
productName = myapp;
productReference = 33AA3112185A7E8D001D767E /* MyApp.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
33AA310A185A7E8D001D767E /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = cockos;
};
buildConfigurationList = 33AA310D185A7E8D001D767E /* Build configuration list for PBXProject "MyApp" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 33AA3109185A7E8D001D767E;
productRefGroup = 33AA3113185A7E8D001D767E /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
33AA3111185A7E8D001D767E /* MyApp */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
33AA3110185A7E8D001D767E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
338536732957A6EB00048720 /* MainMenu.xib in Resources */,
33AA3126185A7E8D001D767E /* Credits.rtf in Resources */,
338536702957A62F00048720 /* MyApp.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3304E16F1FC2253B00290319 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/bin/perl ../WDL/swell/swell_resgen.sh res.rc";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
33AA310E185A7E8D001D767E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33F96581185A7F79004C7070 /* swell-appstub.mm in Sources */,
33F9658B185A7F79004C7070 /* swellappmain.mm in Sources */,
33F9658A185A7F79004C7070 /* swell.cpp in Sources */,
33F96584185A7F79004C7070 /* swell-ini.cpp in Sources */,
3385932D185B555500FDFFEA /* wndsize.cpp in Sources */,
33F96589185A7F79004C7070 /* swell-wnd.mm in Sources */,
33F96582185A7F79004C7070 /* swell-dlg.mm in Sources */,
33F96585185A7F79004C7070 /* swell-kb.mm in Sources */,
33F96586185A7F79004C7070 /* swell-menu.mm in Sources */,
33F96583185A7F79004C7070 /* swell-gdi.mm in Sources */,
338536692957A46300048720 /* myapp.cpp in Sources */,
33F96587185A7F79004C7070 /* swell-misc.mm in Sources */,
3385366B2957A4D300048720 /* main.m in Sources */,
33F96588185A7F79004C7070 /* swell-miscdlg.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
338536712957A6EB00048720 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
338536722957A6EB00048720 /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
33AA311E185A7E8D001D767E /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
33AA311F185A7E8D001D767E /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
33AA3124185A7E8D001D767E /* Credits.rtf */ = {
isa = PBXVariantGroup;
children = (
33AA3125185A7E8D001D767E /* en */,
);
name = Credits.rtf;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
33AA3141185A7E8D001D767E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++98";
CLANG_CXX_LIBRARY = "libstdc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_STRICT_ALIASING = NO;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
33AA3142185A7E8D001D767E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++98";
CLANG_CXX_LIBRARY = "libstdc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_STRICT_ALIASING = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.5;
SDKROOT = macosx;
};
name = Release;
};
33AA3144185A7E8D001D767E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LIBRARY = "libc++";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "MyApp-Prefix.pch";
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
INFOPLIST_FILE = "MyApp-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.9;
PRODUCT_BUNDLE_IDENTIFIER = nobody.swell.myapp;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
33AA3145185A7E8D001D767E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LIBRARY = "libc++";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "MyApp-Prefix.pch";
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
INFOPLIST_FILE = "MyApp-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.9;
PRODUCT_BUNDLE_IDENTIFIER = nobody.swell.myapp;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
33AA310D185A7E8D001D767E /* Build configuration list for PBXProject "MyApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33AA3141185A7E8D001D767E /* Debug */,
33AA3142185A7E8D001D767E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33AA3143185A7E8D001D767E /* Build configuration list for PBXNativeTarget "MyApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33AA3144185A7E8D001D767E /* Debug */,
33AA3145185A7E8D001D767E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 33AA310A185A7E8D001D767E /* Project object */;
}

View File

@@ -0,0 +1,66 @@
SWELL_MyApp
Copyright (C) 2022 and onwards, Cockos Incorporated
LICENSE:
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Minimal SWELL win32/linux/macOS GUI application starting point, feel free to base your applications on this.
NOTE: this project is not configured to be compiled in-place, you should move it to be alongside WDL, e.g.
cp -a ./WDL/swell/swell_myapp ./my_new_app
------
Previous sample project xcode instructions:
How we created the xcode project that compiles this, too:
New Project -> Mac OS X -> Application -> Cocoa Application
Save as...
Add to "Other sources/SWELL": (from swell path) swell-dlg.mm swell-gdi.mm swell-ini.cpp swell-kb.mm swell-menu.mm swell-misc.mm swell-miscdlg.mm swell-wnd.mm swell.cpp swell-appstub.mm swellappmain.mm
Add app_main.cpp main_dialog.cpp to "Other sources"
Go to Frameworks -> Linked Frameworks, add existing framework, Carbon.Framework
go to terminal, to project dir, and run <pathtoswell>/swell_resgen.pl sample_project.rc
Open mainmenu.xib in Interface Builder (doubleclick it in XCode)
+ Delete the default "Window"
+ File->Read class files, find and select "swellappmain.h"
+ Go to Library, Objects, scroll to "Object" , drag to "MainMenu.xib", rename to "Controller", then open its
properties (Cmd+Shift+I, go to class identity tab), choose for Class "SWELLAppController".
+ Select "Application" in MainMenu.xib, go to (Cmd+Shift+I) application identity tab, select "SWELLApplication" for the class.
+ Customize the "NewApplication" menu.
+ Properties on "About NewApplication":
+ set the tag to 40002 (matching resource.h for about)
+ on the connection tab, "Sent Actions", remove the default connection, then drag a new connection to controller (onSysMenuCommand).
+ Properties on "Quit NewApplication":
+ set the tag to 40001 (matching resource.h for quit)
+ on the connection tab, "Sent Actions", remove the default connection, then drag a new connection to controller (onSysMenuCommand).
+ Delete the file/edit/format/view/window/help menus, if you like (or keep some of them if you want)
+ Save and quit IB
Go to Targets->sample_project, hit cmd+I, go to "Properties", and change Principal class to "SWELLApplication"

View File

@@ -0,0 +1 @@
#include <windows.h>

View File

@@ -0,0 +1,83 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "swell.h"
#ifndef SWELL_PROVIDED_BY_APP
// only add this file to your project if you are an application that wishes to publish the SWELL API to its modules/plugins
// the modules should be compiled using SWELL_PROVIDED_BY_APP and include swell-modstub-generic.cpp
#undef _WDL_SWELL_H_API_DEFINED_
#undef SWELL_API_DEFINE
#define SWELL_API_DEFINE(ret, func, parms) {#func, (void *)func },
static struct api_ent
{
const char *name;
void *func;
}
api_table[]=
{
#include "swell.h"
};
static int compfunc(const void *a, const void *b)
{
return strcmp(((struct api_ent*)a)->name,((struct api_ent*)b)->name);
}
extern "C" {
__attribute__ ((visibility ("default"))) void *SWELLAPI_GetFunc(const char *name)
{
if (!name) return (void *)0x100; // version
static int a;
if (!a)
{
a=1;
qsort(api_table,sizeof(api_table)/sizeof(api_table[0]),sizeof(api_table[0]),compfunc);
}
struct api_ent find={name,NULL};
struct api_ent *res=(struct api_ent *)bsearch(&find,api_table,sizeof(api_table)/sizeof(api_table[0]),sizeof(api_table[0]),compfunc);
if (res) return res->func;
return NULL;
}
};
#ifdef SWELL_MAKING_DYLIB
static INT_PTR (*s_AppMain)(int msg, INT_PTR parm1, INT_PTR parm2);
INT_PTR SWELLAppMain(int msg, INT_PTR parm1, INT_PTR parm2)
{
if (s_AppMain) return s_AppMain(msg,parm1,parm2);
return 0;
}
extern "C" {
__attribute__ ((visibility ("default"))) void SWELL_set_app_main(INT_PTR (*AppMain)(int msg, INT_PTR parm1, INT_PTR parm2))
{
s_AppMain = AppMain;
}
};
#endif
#endif

View File

@@ -0,0 +1,61 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "swell.h"
#ifndef SWELL_PROVIDED_BY_APP
// only add this file to your project if you are an application that wishes to publish the SWELL API to its modules/plugins
// the modules should be compiled using SWELL_PROVIDED_BY_APP and include swell-modstub.mm
#undef _WDL_SWELL_H_API_DEFINED_
#undef SWELL_API_DEFINE
#define SWELL_API_DEFINE(ret, func, parms) {#func, (void *)func },
static struct api_ent
{
const char *name;
void *func;
}
api_table[]=
{
#include "swell-functions.h"
};
static int compfunc(const void *a, const void *b)
{
return strcmp(((struct api_ent*)a)->name,((struct api_ent*)b)->name);
}
void *SWELLAPI_GetFunc(const char *name)
{
if (!name) return (void *)0x100; // version
static int a;
if (!a)
{
a=1;
qsort(api_table,sizeof(api_table)/sizeof(api_table[0]),sizeof(api_table[0]),compfunc);
}
struct api_ent find={name,NULL};
struct api_ent *res=(struct api_ent *)bsearch(&find,api_table,sizeof(api_table)/sizeof(api_table[0]),sizeof(api_table[0]),compfunc);
if (res) return res->func;
return NULL;
}
#endif

View File

@@ -0,0 +1,387 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "swell-dlggen.h"
#include "../ptrlist.h"
static HMENU g_swell_defaultmenu,g_swell_defaultmenumodal;
bool SWELL_owned_windows_levelincrease=false;
#include "swell-internal.h"
static SWELL_DialogResourceIndex *resById(SWELL_DialogResourceIndex *reshead, const char *resid)
{
SWELL_DialogResourceIndex *p=reshead;
while (p)
{
if (p->resid == resid) return p;
p=p->_next;
}
return 0;
}
// keep list of modal dialogs
struct modalDlgRet {
HWND hwnd;
bool has_ret;
int ret;
};
static WDL_PtrList<modalDlgRet> s_modalDialogs;
bool IsModalDialogBox(HWND hwnd)
{
if (WDL_NOT_NORMALLY(!hwnd)) return false;
int a = s_modalDialogs.GetSize();
while (a-- > 0)
{
modalDlgRet *r = s_modalDialogs.Get(a);
if (r && r->hwnd == hwnd) return true;
}
return false;
}
HWND DialogBoxIsActive()
{
int a = s_modalDialogs.GetSize();
while (a-- > 0)
{
modalDlgRet *r = s_modalDialogs.Get(a);
if (r && !r->has_ret && r->hwnd) return r->hwnd;
}
return NULL;
}
static SWELL_OSWINDOW s_spare;
static RECT s_spare_rect;
static UINT_PTR s_spare_timer;
static int s_spare_style;
void swell_dlg_destroyspare()
{
if (s_spare_timer)
{
KillTimer(NULL,s_spare_timer);
s_spare_timer=0;
}
if (s_spare)
{
#ifdef SWELL_TARGET_GDK
gdk_window_destroy(s_spare);
#endif
s_spare=NULL;
}
}
static void spareTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwtime)
{
swell_dlg_destroyspare();
}
static int s_last_dlgret;
void EndDialog(HWND wnd, int ret)
{
if (WDL_NOT_NORMALLY(!wnd)) return;
int a = s_modalDialogs.GetSize();
while (a-->0)
{
modalDlgRet *r = s_modalDialogs.Get(a);
if (r && r->hwnd == wnd)
{
r->ret = ret;
if (r->has_ret) return;
r->has_ret=true;
}
}
if (!wnd->m_hashaddestroy)
{
void RecurseDestroyWindow(HWND);
SendMessage(wnd,WM_DESTROY,0,0);
#ifndef SWELL_NO_SPARE_MODALDLG
if (wnd->m_oswindow && wnd->m_visible)
{
swell_dlg_destroyspare();
s_spare_rect = wnd->m_position;
s_spare_style = wnd->m_style;
s_spare = wnd->m_oswindow;
wnd->m_oswindow = NULL;
s_spare_timer = SetTimer(NULL,0,
swell_is_app_inactive()>0 ? 500 : 100,
spareTimer);
}
#endif
RecurseDestroyWindow(wnd);
}
s_last_dlgret = ret;
}
int SWELL_DialogBox(SWELL_DialogResourceIndex *reshead, const char *resid, HWND parent, DLGPROC dlgproc, LPARAM param)
{
SWELL_DialogResourceIndex *p=resById(reshead,resid);
if (resid) // allow modal dialogs to be created without template
{
if (!p||(p->windowTypeFlags&SWELL_DLG_WS_CHILD)) return -1;
}
else if (parent)
{
resid = (const char *)(INT_PTR)(0x400002); // force non-child, force no minimize box
}
int ret=-1;
s_last_dlgret = -1;
HWND hwnd = SWELL_CreateDialog(reshead,resid,parent,dlgproc,param);
// create dialog
if (hwnd)
{
hwnd->Retain();
void SWELL_OnNavigationFocus(HWND ch);
HWND SWELL_GetFocusedChild(HWND h);
SWELL_OnNavigationFocus(SWELL_GetFocusedChild(hwnd));
ReleaseCapture(); // force end of any captures
WDL_PtrKeyedArray<int> restwnds;
extern HWND__ *SWELL_topwindows;
HWND a = SWELL_topwindows;
while (a)
{
if (a!=hwnd)
{
int f=0;
if (a->m_enabled) { EnableWindow(a,FALSE); f|=1; }
if (a->m_israised) { SWELL_SetWindowLevel(a,0); f|=2; }
if (f) restwnds.AddUnsorted((INT_PTR)a,f);
}
a = a->m_next;
}
restwnds.Resort();
SWELL_SetWindowLevel(hwnd,1);
modalDlgRet r = { hwnd,false, -1 };
s_modalDialogs.Add(&r);
if (s_spare && s_spare_style == hwnd->m_style)
{
if (s_spare_timer)
{
KillTimer(NULL,s_spare_timer);
s_spare_timer = 0;
}
SWELL_OSWINDOW w = s_spare;
s_spare = NULL;
int flags = 0;
const int dw = (hwnd->m_position.right-hwnd->m_position.left) -
(s_spare_rect.right - s_spare_rect.left);
const int dh = (hwnd->m_position.bottom-hwnd->m_position.top) -
(s_spare_rect.bottom - s_spare_rect.top);
if (hwnd->m_has_had_position) flags |= 1;
if (dw || dh) flags |= 2;
if (flags == 2)
{
// center on the old window
hwnd->m_position.right -= hwnd->m_position.left;
hwnd->m_position.bottom -= hwnd->m_position.top;
hwnd->m_position.left = s_spare_rect.left - dw/2;
hwnd->m_position.top = s_spare_rect.top - dh/2;
hwnd->m_position.right += hwnd->m_position.left;
hwnd->m_position.bottom += hwnd->m_position.top;
flags = 3;
}
if (flags)
{
if (flags&2) swell_oswindow_begin_resize(w);
swell_oswindow_resize(w, flags, hwnd->m_position);
}
hwnd->m_oswindow = w;
if (!flags)
{
hwnd->m_has_had_position = true;
hwnd->m_position = s_spare_rect;
if (!hwnd->m_hashaddestroy)
{
void swell_recalcMinMaxInfo(HWND hwnd);
swell_recalcMinMaxInfo(hwnd);
}
}
swell_oswindow_focus(hwnd);
ShowWindow(hwnd,SW_SHOWNA);
InvalidateRect(hwnd,NULL,FALSE);
}
else
{
swell_dlg_destroyspare();
ShowWindow(hwnd,SW_SHOW);
}
while (!r.has_ret && !hwnd->m_hashaddestroy)
{
void SWELL_RunMessageLoop();
SWELL_RunMessageLoop();
Sleep(10);
}
ret=r.ret;
s_modalDialogs.DeletePtr(&r);
a = SWELL_topwindows;
while (a)
{
if (a != hwnd)
{
int f = restwnds.Get((INT_PTR)a);
if (!a->m_enabled && (f&1)) EnableWindow(a,TRUE);
if (!a->m_israised && (f&2)) SWELL_SetWindowLevel(a,1);
}
a = a->m_next;
}
hwnd->Release();
}
else
{
ret = s_last_dlgret; // SWELL_CreateDialog() failed, implies WM_INITDIALOG could have called EndDialog()
}
// while in list, do something
return ret;
}
HWND SWELL_CreateDialog(SWELL_DialogResourceIndex *reshead, const char *resid, HWND parent, DLGPROC dlgproc, LPARAM param)
{
int forceStyles=0; // 1=resizable, 2=no minimize, 4=no close
bool forceNonChild=false;
if ((((INT_PTR)resid)&~0xf)==0x400000)
{
forceStyles = (int) (((INT_PTR)resid)&0xf);
if (forceStyles) forceNonChild=true;
resid=0;
}
SWELL_DialogResourceIndex *p=resById(reshead,resid);
if (!p&&resid) return 0;
RECT r={0,0,SWELL_UI_SCALE(p ? p->width : 300), SWELL_UI_SCALE(p ? p->height : 200) };
HWND owner=NULL;
if (!forceNonChild && parent && (!p || (p->windowTypeFlags&SWELL_DLG_WS_CHILD)))
{
}
else
{
owner = parent;
parent = NULL; // top level window
}
HWND__ *h = new HWND__(parent,0,&r,NULL,false,NULL,NULL, owner);
if (forceNonChild || (p && !(p->windowTypeFlags&SWELL_DLG_WS_CHILD)))
{
if ((forceStyles&1) || (p && (p->windowTypeFlags&SWELL_DLG_WS_RESIZABLE)))
h->m_style |= WS_THICKFRAME|WS_CAPTION;
else h->m_style |= WS_CAPTION;
}
else if (!p && !parent) h->m_style |= WS_CAPTION;
else if (parent && (!p || (p->windowTypeFlags&SWELL_DLG_WS_CHILD))) h->m_style |= WS_CHILD;
if (p)
{
h->m_style |= p->windowTypeFlags & (WS_CLIPSIBLINGS);
if (p->windowTypeFlags&SWELL_DLG_WS_DROPTARGET)
h->m_exstyle|=WS_EX_ACCEPTFILES;
}
h->Retain();
if (p)
{
p->createFunc(h,p->windowTypeFlags);
if (p->title) SetWindowText(h,p->title);
h->m_dlgproc = dlgproc;
h->m_wndproc = SwellDialogDefaultWindowProc;
HWND hFoc=h->m_children;
while (hFoc)
{
if (hFoc->m_wantfocus && hFoc->m_visible && hFoc->m_enabled)
{
h->m_focused_child = hFoc; // default focus to hFoc, but set focus more aggressively after WM_INITDIALOG if the dlgproc returns 1
break;
}
hFoc=hFoc->m_next;
}
if (hFoc) hFoc->Retain();
if (h->m_dlgproc(h,WM_INITDIALOG,(WPARAM)hFoc,param))
{
if (hFoc && hFoc->m_wantfocus && hFoc->m_visible && hFoc->m_enabled)
{
if (!h->m_hashaddestroy && !hFoc->m_hashaddestroy)
SetFocus(hFoc);
}
}
if (hFoc) hFoc->Release();
}
else
{
h->m_wndproc = (WNDPROC)dlgproc;
h->m_wndproc(h,WM_CREATE,0,param);
}
HWND rv = h->m_hashaddestroy ? NULL : h;
h->Release();
return rv;
}
HMENU SWELL_GetDefaultWindowMenu() { return g_swell_defaultmenu; }
void SWELL_SetDefaultWindowMenu(HMENU menu)
{
g_swell_defaultmenu=menu;
}
HMENU SWELL_GetDefaultModalWindowMenu()
{
return g_swell_defaultmenumodal;
}
void SWELL_SetDefaultModalWindowMenu(HMENU menu)
{
g_swell_defaultmenumodal=menu;
}
SWELL_DialogResourceIndex *SWELL_curmodule_dialogresource_head; // this eventually will go into a per-module stub file
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,280 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
DialogBox emulation is here. To declare the resource at a global level, use (in any source file that includes this file and resource.h):
#ifdef MAC
SWELL_DEFINE_DIALOG_RESOURCE_BEGIN(IDD_SOMEDIALOG,0,"Dialog Box Title",222,55,1.8) // width, height, scale (1.8 is usually good)
BEGIN
DEFPUSHBUTTON "OK",IDOK,117,33,47,14
CONTROL "Expand MIDI tracks to new REAPER tracks ",IDC_CHECK1,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,7,214,10
CONTROL "Merge MIDI tempo map to project tempo map at ",
IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,19,
214,10
PUSHBUTTON "Cancel",IDCANCEL,168,33,50,14
END
SWELL_DEFINE_DIALOG_RESOURCE_END(IDD_SOMEDIALOG)
#endif
This file also provides functions to dynamically create controls in a view from a win32 resource script.
*/
#ifndef _SWELL_DLGGEN_H_
#define _SWELL_DLGGEN_H_
#ifdef BEGIN
#undef BEGIN
#endif
#ifdef END
#undef END
#endif
struct SWELL_DlgResourceEntry
{
const char *str1;
int flag1;
const char *str2;
int p1; // often used for ID
// todo: see at runtime if some of these can be short instead of int (p2-p6 probably can, but not completely sure) -- i.e. do we use any
// big values in flags. note: it can't be unsigned short, because we want negative values.
int p2, p3, p4, p5, p6; // meaning is dependent on class
};
#define BEGIN {NULL,
#define END },
#define PUSHBUTTON }, { "__SWELL_BUTTON", 0,
#define DEFPUSHBUTTON }, { "__SWELL_BUTTON", 1,
#define EDITTEXT }, { "__SWELL_EDIT", 0, "",
#define CTEXT }, { "__SWELL_LABEL", 0,
#define LTEXT }, { "__SWELL_LABEL", -1,
#define RTEXT }, { "__SWELL_LABEL", 1,
#define CONTROL }, {
#define COMBOBOX }, { "__SWELL_COMBO", 0, "",
#define GROUPBOX }, { "__SWELL_GROUP", 0,
#define CHECKBOX }, { "__SWELL_CHECKBOX", 0,
#define LISTBOX }, { "__SWELL_LISTBOX", 0, "",
#define ICON }, { "__SWELL_ICON", 0, (const char*)(INT_PTR)
#define NOT
// flags we may use
#define CBS_DROPDOWNLIST 0x0003L
#define CBS_DROPDOWN 0x0002L
#define CBS_SORT 0x0100L
#define ES_PASSWORD 0x0020L
#define ES_READONLY 0x0800L
#define ES_WANTRETURN 0x1000L
#define ES_NUMBER 0x2000L
#define SS_LEFT 0
#define SS_CENTER 0x1L
#define SS_RIGHT 0x2L
#define SS_BLACKRECT 0x4L
#define SS_BLACKFRAME (SS_BLACKRECT)
#define SS_LEFTNOWORDWRAP 0xCL
#define SS_ETCHEDHORZ 0x10L
#define SS_ETCHEDVERT 0x11L
#define SS_ETCHEDFRAME 0x12L
#define SS_TYPEMASK 0x1FL
#define SS_NOPREFIX 0x80L
#define SS_NOTIFY 0x0100L
#define BS_LEFTTEXT 0x0020L
#define BS_LEFT 0x100L
#define BS_CENTER 0x300L
#define BS_XPOSITION_MASK BS_CENTER
#define BS_GROUPBOX 0x20000000
#define BS_DEFPUSHBUTTON 0x10000000
#define BS_PUSHBUTTON 0x8000000
#define LVS_LIST 0 /* 0x0003 */
#define LVS_NOCOLUMNHEADER 0x4000
#define LVS_NOSORTHEADER 0x8000
#define LVS_REPORT 0x0001
#define LVS_TYPEMASK 0x0003
#define LVS_SINGLESEL 0x0004
#define LVS_OWNERDATA 0x1000
#define LVS_SORTASCENDING 0x0010
#define LVS_SORTDESCENDING 0x0020
#define LBS_SORT 0x0002L
#define LBS_OWNERDRAWFIXED 0x0010L
#define LBS_EXTENDEDSEL 0x0800L
#define ES_LEFT 0
#define ES_CENTER 1
#define ES_RIGHT 2
#define ES_MULTILINE 4
#define ES_AUTOHSCROLL 0x80
// flags we ignore
#define LVS_SHOWSELALWAYS 0
#define LVS_SHAREIMAGELISTS 0
#define ES_AUTOVSCROLL 0
#define GROUP 0
#define PBS_SMOOTH 0
#define CBS_AUTOHSCROLL 0
#define TBS_NOTICKS 0
#define TBS_TOP 0
#define TBS_BOTH 0
#define LBS_NOINTEGRALHEIGHT 0
#define TVS_HASLINES 0
#define TVS_LINESATROOT 0
#define TVS_SHOWSELALWAYS 0
#define TVS_HASBUTTONS 0
#define TVS_TRACKSELECT 0
#define TVS_NONEVENHEIGHT 0
#define TVS_NOTOOLTIPS 0
#define BS_FLAT 0
#define SS_SUNKEN 0
#define BS_RIGHT 0
#define WS_EX_STATICEDGE 0
#define WS_EX_RIGHT 0
#define SS_CENTERIMAGE 0
#define WS_CLIPCHILDREN 0
// more ignore flags for vc11+
#define LVS_ALIGNLEFT 0 /* 0x0800 */
#ifndef IDC_STATIC
#define IDC_STATIC 0
#endif
#define SWELL_DLG_WS_CHILD 1
#define SWELL_DLG_WS_RESIZABLE 2
#define SWELL_DLG_WS_FLIPPED 4
#define SWELL_DLG_WS_NOAUTOSIZE 8
#define SWELL_DLG_WS_OPAQUE 16
#define SWELL_DLG_WS_DROPTARGET 32
typedef struct SWELL_DialogResourceIndex
{
const char *resid;
const char *title;
int windowTypeFlags;
void (*createFunc)(HWND, int);
int width,height;
struct SWELL_DialogResourceIndex *_next;
} SWELL_DialogResourceIndex;
typedef struct SWELL_CursorResourceIndex
{
const char *resid;
const char *resname;
POINT hotspot;
HCURSOR cachedCursor;
struct SWELL_CursorResourceIndex *_next;
} SWELL_CursorResourceIndex;
class SWELL_DialogRegHelper {
public:
SWELL_DialogResourceIndex m_rec;
SWELL_DialogRegHelper(SWELL_DialogResourceIndex **h, void (*cf)(HWND,int), int recid, int flags,
const char *titlestr, int wid, int hei, double xscale, double yscale)
{
if (recid)
{
m_rec.resid=MAKEINTRESOURCE(recid);
m_rec.title=titlestr;
m_rec.windowTypeFlags=flags;
m_rec.createFunc=cf;
m_rec.width=(int)(wid*xscale);
m_rec.height=(int)(hei*yscale);
m_rec._next=*h;
*h = &m_rec;
}
}
};
#ifdef _DEBUG
#include "../assocarray.h"
class SWELL_DialogRegValidator
{
public:
SWELL_DialogRegValidator(const SWELL_DlgResourceEntry *recs, size_t recs_sz)
{
if (recs_sz>1)
{
// check for duplicate IDs
WDL_IntKeyedArray<bool> tmp;
for (size_t x = 0; x < recs_sz; x ++)
{
const SWELL_DlgResourceEntry *list = recs + x;
const int idx = strncmp(list->str1,"__SWELL_",8) ? list->flag1 : list->p1;
if (idx != 0 && idx != -1)
{
WDL_ASSERT(!tmp.Get(idx));
tmp.Insert(idx,true);
}
}
}
}
};
#define SWELL_VALIDATE_DIALOG_RESOURCE(v,r) static SWELL_DialogRegValidator v(r+1, sizeof(r)/sizeof(r[0])-1);
#else
#define SWELL_VALIDATE_DIALOG_RESOURCE(v,r)
#endif
#define SWELL_DEFINE_DIALOG_RESOURCE_BEGIN(recid, flags, titlestr, wid, hei, scale) \
static void SWELL__dlg_cf__##recid(HWND view, int wflags); \
const float __swell_dlg_scale__##recid = (float) (scale); \
static SWELL_DialogRegHelper __swell_dlg_helper_##recid(&SWELL_curmodule_dialogresource_head, SWELL__dlg_cf__##recid, recid,flags,titlestr,wid,hei,scale,(scale)*(SWELL_DLG_SCALE_AUTOGEN_YADJ)); \
static const SWELL_DlgResourceEntry __swell_dlg_list__##recid[]={
#define SWELL_DEFINE_DIALOG_RESOURCE_END(recid ) }; \
SWELL_VALIDATE_DIALOG_RESOURCE( __swell_dlg_validator__##recid, __swell_dlg_list__##recid) \
static void SWELL__dlg_cf__##recid(HWND view, int wflags) { \
SWELL_MakeSetCurParms(__swell_dlg_scale__##recid,__swell_dlg_scale__##recid * (SWELL_DLG_SCALE_AUTOGEN_YADJ),0,0,view,false,!(wflags&SWELL_DLG_WS_NOAUTOSIZE)); \
SWELL_GenerateDialogFromList(__swell_dlg_list__##recid+1,sizeof(__swell_dlg_list__##recid)/sizeof(__swell_dlg_list__##recid[0])-1); \
}
#ifndef SWELL_DLG_SCALE_AUTOGEN_YADJ
#define SWELL_DLG_SCALE_AUTOGEN_YADJ 1.0
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,797 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides basic win32 GDI--> null translation.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "swell-internal.h"
#include "../wdlcstring.h"
const char *g_swell_deffont_face = "Arial";
const char *swell_last_font_filename;
swell_colortheme g_swell_ctheme = {
#define __def_theme_ent(x,c) (c),
#define __def_theme_ent_fb(x,c,fb) (c),
SWELL_GENERIC_THEMEDEFS(__def_theme_ent,__def_theme_ent_fb)
#undef __def_theme_ent
#undef __def_theme_ent_fb
};
int GetSysColor(int idx)
{
switch (idx)
{
case COLOR_WINDOW:
case COLOR_3DFACE:
case COLOR_BTNFACE: return g_swell_ctheme._3dface;
case COLOR_3DSHADOW: return g_swell_ctheme._3dshadow;
case COLOR_3DHILIGHT: return g_swell_ctheme._3dhilight;
case COLOR_3DDKSHADOW: return g_swell_ctheme._3ddkshadow;
case COLOR_BTNTEXT: return g_swell_ctheme.button_text;
case COLOR_INFOBK: return g_swell_ctheme.info_bk;
case COLOR_INFOTEXT: return g_swell_ctheme.info_text;
case COLOR_SCROLLBAR: return g_swell_ctheme.scrollbar;
}
return 0;
}
int g_swell_ui_scale = 256;
int SWELL_GetScaling256(void)
{
return g_swell_ui_scale;
}
#ifndef SWELL_LICE_GDI
#include "../mutex.h"
#include "../ptrlist.h"
#include "swell-gdi-internalpool.h"
HDC SWELL_CreateGfxContext(void *c)
{
HDC__ *ctx=SWELL_GDP_CTX_NEW();
return ctx;
}
HDC SWELL_CreateMemContext(HDC hdc, int w, int h)
{
// we could use CGLayer here, but it's 10.4+ and seems to be slower than this
// if (w&1) w++;
void *buf=calloc(w*4,h);
if (!buf) return 0;
HDC__ *ctx=SWELL_GDP_CTX_NEW();
ctx->ownedData=buf;
SetTextColor(ctx,0);
return ctx;
}
void SWELL_DeleteGfxContext(HDC ctx)
{
HDC__ *ct=(HDC__ *)ctx;
if (HDC_VALID(ct))
{
if (ct->ownedData)
{
free(ct->ownedData);
}
SWELL_GDP_CTX_DELETE(ct);
}
}
HPEN CreatePen(int attr, int wid, int col)
{
return CreatePenAlpha(attr,wid,col,1.0f);
}
HBRUSH CreateSolidBrush(int col)
{
return CreateSolidBrushAlpha(col,1.0f);
}
HPEN CreatePenAlpha(int attr, int wid, int col, float alpha)
{
HGDIOBJ__ *pen=GDP_OBJECT_NEW();
pen->type=TYPE_PEN;
pen->wid=wid<0?0:wid;
// pen->color=CreateColor(col,alpha);
return pen;
}
HBRUSH CreateSolidBrushAlpha(int col, float alpha)
{
HGDIOBJ__ *brush=GDP_OBJECT_NEW();
brush->type=TYPE_BRUSH;
// brush->color=CreateColor(col,alpha);
brush->wid=0;
return brush;
}
#define FONTSCALE 0.9
HFONT CreateFont(int lfHeight, int lfWidth, int lfEscapement, int lfOrientation, int lfWeight, char lfItalic,
char lfUnderline, char lfStrikeOut, char lfCharSet, char lfOutPrecision, char lfClipPrecision,
char lfQuality, char lfPitchAndFamily, const char *lfFaceName)
{
HGDIOBJ__ *font=GDP_OBJECT_NEW();
font->type=TYPE_FONT;
float fontwid=lfHeight;
if (!fontwid) fontwid=lfWidth;
if (fontwid<0)fontwid=-fontwid;
if (fontwid < 2 || fontwid > 8192) fontwid=10;
return font;
}
HFONT SWELL_GetDefaultFont()
{
return NULL;
}
HFONT CreateFontIndirect(LOGFONT *lf)
{
return CreateFont(lf->lfHeight, lf->lfWidth,lf->lfEscapement, lf->lfOrientation, lf->lfWeight, lf->lfItalic,
lf->lfUnderline, lf->lfStrikeOut, lf->lfCharSet, lf->lfOutPrecision,lf->lfClipPrecision,
lf->lfQuality, lf->lfPitchAndFamily, lf->lfFaceName);
}
int GetTextFace(HDC ctx, int nCount, LPTSTR lpFaceName)
{
if (lpFaceName) lpFaceName[0]=0;
return 0;
}
void DeleteObject(HGDIOBJ pen)
{
if (HGDIOBJ_VALID(pen))
{
HGDIOBJ__ *p=(HGDIOBJ__ *)pen;
if (--p->additional_refcnt < 0)
{
if (p->type == TYPE_PEN || p->type == TYPE_BRUSH || p->type == TYPE_FONT || p->type == TYPE_BITMAP)
{
if (p->type == TYPE_PEN || p->type == TYPE_BRUSH)
if (p->wid<0) return;
GDP_OBJECT_DELETE(p);
}
// JF> don't free unknown objects, this should never happen anyway: else free(p);
}
}
}
HGDIOBJ SelectObject(HDC ctx, HGDIOBJ pen)
{
HDC__ *c=(HDC__ *)ctx;
HGDIOBJ__ *p=(HGDIOBJ__ *) pen;
HGDIOBJ__ **mod=0;
if (!HDC_VALID(c)||!p) return 0;
if (p == (HGDIOBJ__ *)TYPE_PEN) mod=&c->curpen;
else if (p == (HGDIOBJ__ *)TYPE_BRUSH) mod=&c->curbrush;
else if (p == (HGDIOBJ__ *)TYPE_FONT) mod=&c->curfont;
if (mod)
{
HGDIOBJ__ *np=*mod;
*mod=0;
return np?np:p;
}
if (!HGDIOBJ_VALID(p)) return 0;
if (p->type == TYPE_PEN) mod=&c->curpen;
else if (p->type == TYPE_BRUSH) mod=&c->curbrush;
else if (p->type == TYPE_FONT) mod=&c->curfont;
else return 0;
HGDIOBJ__ *op=*mod;
if (!op) op=(HGDIOBJ__ *)(INT_PTR)p->type;
if (op != p)
{
*mod=p;
if (p->type == TYPE_FONT)
{
}
}
return op;
}
void SWELL_FillRect(HDC ctx, const RECT *r, HBRUSH br)
{
HDC__ *c=(HDC__ *)ctx;
HGDIOBJ__ *b=(HGDIOBJ__ *) br;
if (!HDC_VALID(c) || !HGDIOBJ_VALID(b,TYPE_BRUSH)) return;
if (b->wid<0) return;
}
void RoundRect(HDC ctx, int x, int y, int x2, int y2, int xrnd, int yrnd)
{
xrnd/=3;
yrnd/=3;
POINT pts[10]={ // todo: curves between edges
{x,y+yrnd},
{x+xrnd,y},
{x2-xrnd,y},
{x2,y+yrnd},
{x2,y2-yrnd},
{x2-xrnd,y2},
{x+xrnd,y2},
{x,y2-yrnd},
{x,y+yrnd},
{x+xrnd,y},
};
WDL_GDP_Polygon(ctx,pts,sizeof(pts)/sizeof(pts[0]));
}
void Ellipse(HDC ctx, int l, int t, int r, int b)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)) return;
//CGRect rect=CGRectMake(l,t,r-l,b-t);
if (HGDIOBJ_VALID(c->curbrush,TYPE_BRUSH) && c->curbrush->wid >=0)
{
}
if (HGDIOBJ_VALID(c->curpen,TYPE_PEN) && c->curpen->wid >= 0)
{
}
}
void Rectangle(HDC ctx, int l, int t, int r, int b)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)) return;
if (HGDIOBJ_VALID(c->curbrush,TYPE_BRUSH) && c->curbrush->wid >= 0)
{
}
if (HGDIOBJ_VALID(c->curpen,TYPE_PEN) && c->curpen->wid >= 0)
{
}
}
HGDIOBJ GetStockObject(int wh)
{
switch (wh)
{
case NULL_BRUSH:
{
static HGDIOBJ__ br={0,};
br.type=TYPE_BRUSH;
br.wid=-1;
return &br;
}
case NULL_PEN:
{
static HGDIOBJ__ pen={0,};
pen.type=TYPE_PEN;
pen.wid=-1;
return &pen;
}
}
return 0;
}
void Polygon(HDC ctx, POINT *pts, int npts)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)) return;
if (((!HGDIOBJ_VALID(c->curbrush,TYPE_BRUSH)||c->curbrush->wid<0) &&
(!HGDIOBJ_VALID(c->curpen,TYPE_PEN)||c->curpen->wid<0)) || npts<2) return;
}
void MoveToEx(HDC ctx, int x, int y, POINT *op)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)) return;
if (op)
{
op->x = (int) (c->lastpos_x);
op->y = (int) (c->lastpos_y);
}
c->lastpos_x=(float)x;
c->lastpos_y=(float)y;
}
void PolyBezierTo(HDC ctx, POINT *pts, int np)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)||!HGDIOBJ_VALID(c->curpen,TYPE_PEN)||c->curpen->wid<0||np<3) return;
int x;
float xp,yp;
for (x = 0; x < np-2; x += 3)
{
xp=(float)pts[x+2].x;
yp=(float)pts[x+2].y;
}
c->lastpos_x=(float)xp;
c->lastpos_y=(float)yp;
}
void SWELL_LineTo(HDC ctx, int x, int y)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)||!HGDIOBJ_VALID(c->curpen,TYPE_PEN)||c->curpen->wid<0) return;
float fx=(float)x,fy=(float)y;
c->lastpos_x=fx;
c->lastpos_y=fy;
}
void PolyPolyline(HDC ctx, POINT *pts, DWORD *cnts, int nseg)
{
HDC__ *c=(HDC__ *)ctx;
if (!HDC_VALID(c)||!HGDIOBJ_VALID(c->curpen,TYPE_PEN)||c->curpen->wid<0||nseg<1) return;
while (nseg-->0)
{
DWORD cnt=*cnts++;
if (!cnt) continue;
if (!--cnt) { pts++; continue; }
pts++;
while (cnt--)
{
pts++;
}
}
}
void *SWELL_GetCtxGC(HDC ctx)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return 0;
return NULL;
}
void SWELL_SetPixel(HDC ctx, int x, int y, int c)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return;
}
BOOL GetTextMetrics(HDC ctx, TEXTMETRIC *tm)
{
HDC__ *ct=(HDC__ *)ctx;
if (tm) // give some sane defaults
{
tm->tmInternalLeading=3;
tm->tmAscent=12;
tm->tmDescent=4;
tm->tmHeight=16;
tm->tmAveCharWidth = 10;
}
if (!HDC_VALID(ct)||!tm) return 0;
return 1;
}
int DrawText(HDC ctx, const char *buf, int buflen, RECT *r, int align)
{
WDL_ASSERT((align & DT_SINGLELINE) || !(align & (DT_VCENTER | DT_BOTTOM)));
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return 0;
if (r && (align&DT_CALCRECT))
{
r->top=r->left=0;
r->bottom=10;
r->right = ( buflen < 0 ? strlen(buf) : buflen ) *8;
}
else printf("DrawText: %s\n",buf);
return 10;
}
void SetBkColor(HDC ctx, int col)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return;
ct->curbkcol=col;
}
void SetBkMode(HDC ctx, int col)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return;
ct->curbkmode=col;
}
int GetTextColor(HDC ctx)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return -1;
return ct->cur_text_color_int;
}
void SetTextColor(HDC ctx, int col)
{
HDC__ *ct=(HDC__ *)ctx;
if (!HDC_VALID(ct)) return;
ct->cur_text_color_int = col;
}
HICON LoadNamedImage(const char *name, bool alphaFromMask)
{
return 0; // todo
}
void DrawImageInRect(HDC ctx, HICON img, const RECT *r)
{
// todo
}
void SWELL_SetViewGL(HWND h, char wantGL)
{
}
bool SWELL_GetViewGL(HWND h)
{
return false;
}
bool SWELL_SetGLContextToView(HWND h)
{
return false;
}
BOOL GetObject(HICON icon, int bmsz, void *_bm)
{
memset(_bm,0,bmsz);
if (bmsz != sizeof(BITMAP)) return false;
HGDIOBJ__ *i = (HGDIOBJ__ *)icon;
if (!HGDIOBJ_VALID(i,TYPE_BITMAP)) return false;
//BITMAP *bm=(BITMAP *)_bm;
return false;
}
void BitBltAlphaFromMem(HDC hdcOut, int x, int y, int w, int h, void *inbufptr, int inbuf_span, int inbuf_h, int xin, int yin, int mode, bool useAlphaChannel, float opacity)
{
}
void BitBltAlpha(HDC hdcOut, int x, int y, int w, int h, HDC hdcIn, int xin, int yin, int mode, bool useAlphaChannel, float opacity)
{
}
void BitBlt(HDC hdcOut, int x, int y, int w, int h, HDC hdcIn, int xin, int yin, int mode)
{
}
void StretchBlt(HDC hdcOut, int x, int y, int w, int h, HDC hdcIn, int xin, int yin, int srcw, int srch, int mode)
{
}
void StretchBltFromMem(HDC hdcOut, int x, int y, int w, int h, const void *bits, int srcw, int srch, int srcspan)
{
}
void SWELL_PushClipRegion(HDC ctx)
{
// HDC__ *ct=(HDC__ *)ctx;
}
void SWELL_SetClipRegion(HDC ctx, const RECT *r)
{
// HDC__ *ct=(HDC__ *)ctx;
}
void SWELL_PopClipRegion(HDC ctx)
{
// HDC__ *ct=(HDC__ *)ctx;
}
void *SWELL_GetCtxFrameBuffer(HDC ctx)
{
HDC__ *ct=(HDC__ *)ctx;
if (HDC_VALID(ct)) return ct->ownedData;
return 0;
}
HDC GetDC(HWND h)
{
return NULL;
}
HDC GetWindowDC(HWND h)
{
return NULL;
}
void ReleaseDC(HWND h, HDC hdc)
{
}
void SWELL_FillDialogBackground(HDC hdc, const RECT *r, int level)
{
}
HGDIOBJ SWELL_CloneGDIObject(HGDIOBJ a)
{
if (HGDIOBJ_VALID(a))
{
a->additional_refcnt++;
return a;
}
return NULL;
}
HDC BeginPaint(HWND hwnd, PAINTSTRUCT *ps)
{
if (!ps) return 0;
memset(ps,0,sizeof(PAINTSTRUCT));
if (!hwnd) return 0;
return NULL;
}
HBITMAP CreateBitmap(int width, int height, int numplanes, int bitsperpixel, unsigned char* bits)
{
return NULL;
}
HICON CreateIconIndirect(ICONINFO* iconinfo)
{
return NULL;
}
HIMAGELIST ImageList_CreateEx()
{
return (HIMAGELIST)new WDL_PtrList<HGDIOBJ__>;
}
BOOL ImageList_Remove(HIMAGELIST list, int idx)
{
WDL_PtrList<HGDIOBJ__>* imglist=(WDL_PtrList<HGDIOBJ__>*)list;
if (imglist && idx < imglist->GetSize())
{
if (idx < 0)
{
int x,n=imglist->GetSize();
for (x=0;x<n;x++)
{
HGDIOBJ__ *a = imglist->Get(x);
if (a) DeleteObject(a);
}
imglist->Empty();
}
else
{
HGDIOBJ__ *a = imglist->Get(idx);
imglist->Set(idx, NULL);
if (a) DeleteObject(a);
}
return TRUE;
}
return FALSE;
}
void ImageList_Destroy(HIMAGELIST list)
{
if (!list) return;
WDL_PtrList<HGDIOBJ__> *p=(WDL_PtrList<HGDIOBJ__>*)list;
ImageList_Remove(list,-1);
delete p;
}
int ImageList_ReplaceIcon(HIMAGELIST list, int offset, HICON image)
{
if (!image || !list) return -1;
WDL_PtrList<HGDIOBJ__> *l=(WDL_PtrList<HGDIOBJ__> *)list;
HGDIOBJ__ *imgsrc = (HGDIOBJ__*)image;
if (!HGDIOBJ_VALID(imgsrc,TYPE_BITMAP)) return -1;
HGDIOBJ__* icon=GDP_OBJECT_NEW();
icon->type=TYPE_BITMAP;
icon->wid=1;
// todo: copy underlying image
image = (HICON) icon;
if (offset<0||offset>=l->GetSize())
{
l->Add(image);
offset=l->GetSize()-1;
}
else
{
HICON old=l->Get(offset);
l->Set(offset,image);
if (old) DeleteObject(old);
}
return offset;
}
int ImageList_Add(HIMAGELIST list, HBITMAP image, HBITMAP mask)
{
if (!image || !list) return -1;
WDL_PtrList<HGDIOBJ__> *l=(WDL_PtrList<HGDIOBJ__> *)list;
HGDIOBJ__ *imgsrc = (HGDIOBJ__*)image;
if (!HGDIOBJ_VALID(imgsrc,TYPE_BITMAP)) return -1;
HGDIOBJ__* icon=GDP_OBJECT_NEW();
icon->type=TYPE_BITMAP;
icon->wid=1;
// todo: copy underlying image
image = (HICON) icon;
l->Add(image);
return l->GetSize();
}
int AddFontResourceEx(LPCTSTR str, DWORD fl, void *pdv)
{
return 0;
}
int GetGlyphIndicesW(HDC ctx, wchar_t *buf, int len, unsigned short *indices, int flags)
{
int i;
for (i=0; i < len; ++i) indices[i]=(flags == GGI_MARK_NONEXISTING_GLYPHS ? 0xFFFF : 0);
return 0;
}
#endif // !SWELL_LICE_GDI
#ifdef SWELL__MAKE_THEME
void print_ent(const char *x, int c, const char *def)
{
if (def)
printf("; %s #%02x%02x%02x ; defaults to %s\n",x,GetRValue(c),GetGValue(c),GetBValue(c),def);
else
{
if (strstr(x,"_size") ||
strstr(x,"_height") ||
strstr(x,"_width"))
printf("%s %d\n",x,c);
else printf("%s #%02x%02x%02x\n",x,GetRValue(c),GetGValue(c),GetBValue(c));
}
}
int main()
{
#define __def_theme_ent(x,c) print_ent(#x,c,NULL);
#define __def_theme_ent_fb(x,c,fb) print_ent(#x,c,#fb);
printf("default_font_face %s\n",g_swell_deffont_face);
SWELL_GENERIC_THEMEDEFS(__def_theme_ent,__def_theme_ent_fb)
return 0;
}
#else
void swell_load_color_theme(const char *fn)
{
FILE *fp = WDL_fopenA(fn,"r");
if (fp)
{
swell_colortheme load;
memset(&load,-1,sizeof(load));
char buf[1024];
for (;;)
{
if (!fgets(buf,sizeof(buf),fp)) break;
char *p = buf;
while (*p == ' ' || *p == '\t') p++;
char *np = p;
while (*np > 0 && (*np == '_' || isalnum(*np))) np++;
if (!*np || np == p) continue;
*np++ = 0;
while (*np == ' ' || *np == '\t') np++;
if(!stricmp(p,"default_font_face"))
{
if (*np > 0 && !isspace(*np))
{
char *b = strdup(np);
g_swell_deffont_face = b;
while (*b && *b != ';' && *b != '#') b++;
while (b>g_swell_deffont_face && b[-1] > 0 && isspace(b[-1])) b--;
*b=0;
}
continue;
}
int col;
if (*np == '#')
{
np++;
char *next;
col = strtol(np,&next,16);
if (next != np+6)
{
if (next != np+3) continue;
col = ((col&0xf)<<4) | ((col&0xf0)<<8) | ((col&0xf00)<<12);
}
}
else if (*np >= '0' && *np <= '9')
{
col = atoi(np);
}
else continue;
if(0){}
#define __def_theme_ent(x,c) else if (!stricmp(p,#x)) load.x = col;
#define __def_theme_ent_fb(x,c,fb) else if (!stricmp(p,#x)) load.x = col;
SWELL_GENERIC_THEMEDEFS(__def_theme_ent,__def_theme_ent_fb)
#undef __def_theme_ent
#undef __def_theme_ent_fb
}
#define __def_theme_ent(x,c) g_swell_ctheme.x = load.x == -1 ? c : load.x;
#define __def_theme_ent_fb(x,c,fb) g_swell_ctheme.x = load.x == -1 ? g_swell_ctheme.fb : load.x;
SWELL_GENERIC_THEMEDEFS(__def_theme_ent,__def_theme_ent_fb)
#undef __def_theme_ent
#undef __def_theme_ent_fb
fclose(fp);
}
}
// load color theme
class swellColorThemeLoader
{
public:
swellColorThemeLoader()
{
char buf[1024];
GetModuleFileName(NULL,buf,sizeof(buf));
WDL_remove_filepart(buf);
lstrcatn(buf,"/libSwell.colortheme",sizeof(buf));
swell_load_color_theme(buf);
}
};
swellColorThemeLoader g_swell_themeloader;
#endif
#endif

View File

@@ -0,0 +1,222 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
// used for HDC/HGDIOBJ pooling (to avoid excess heap use), used by swell-gdi.mm and swell-gdi-generic.cpp
*/
#if defined(_DEBUG)
#define SWELL_GDI_DEBUG
#endif
static WDL_Mutex *m_ctxpool_mutex;
#ifdef SWELL_GDI_DEBUG
#include "../ptrlist.h"
static WDL_PtrList<HDC__> *m_ctxpool_debug;
static WDL_PtrList<HGDIOBJ__> *m_objpool_debug;
#else
static HDC__ *m_ctxpool;
static int m_ctxpool_size;
static HGDIOBJ__ *m_objpool;
static int m_objpool_size;
#endif
HDC__ *SWELL_GDP_CTX_NEW()
{
if (!m_ctxpool_mutex) m_ctxpool_mutex=new WDL_Mutex;
HDC__ *p=NULL;
#ifdef SWELL_GDI_DEBUG
m_ctxpool_mutex->Enter();
if (!m_ctxpool_debug) m_ctxpool_debug = new WDL_PtrList<HDC__>;
if (m_ctxpool_debug->GetSize() > 8192)
{
p = m_ctxpool_debug->Get(0);
m_ctxpool_debug->Delete(0);
memset(p,0,sizeof(*p));
}
m_ctxpool_mutex->Leave();
#else
if (m_ctxpool)
{
m_ctxpool_mutex->Enter();
if ((p=m_ctxpool))
{
m_ctxpool=p->_next;
m_ctxpool_size--;
memset(p,0,sizeof(*p));
}
m_ctxpool_mutex->Leave();
}
#endif
if (!p)
{
// printf("alloc ctx\n");
p=(HDC__ *)calloc(sizeof(HDC__)+128,1); // extra space in case things want to use it (i.e. swell-gdi-lice does)
}
return p;
}
static void SWELL_GDP_CTX_DELETE(HDC__ *p)
{
if (!m_ctxpool_mutex) m_ctxpool_mutex=new WDL_Mutex;
if (WDL_NOT_NORMALLY(!p || p->_infreelist)) return;
memset(p,0,sizeof(*p));
#ifdef SWELL_GDI_DEBUG
m_ctxpool_mutex->Enter();
p->_infreelist=true;
if (!m_ctxpool_debug) m_ctxpool_debug = new WDL_PtrList<HDC__>;
m_ctxpool_debug->Add(p);
m_ctxpool_mutex->Leave();
#else
if (m_ctxpool_size<100)
{
m_ctxpool_mutex->Enter();
p->_infreelist=true;
p->_next = m_ctxpool;
m_ctxpool = p;
m_ctxpool_size++;
m_ctxpool_mutex->Leave();
}
else
{
// printf("free ctx\n");
free(p);
}
#endif
}
static HGDIOBJ__ *GDP_OBJECT_NEW()
{
if (!m_ctxpool_mutex) m_ctxpool_mutex=new WDL_Mutex;
HGDIOBJ__ *p=NULL;
#ifdef SWELL_GDI_DEBUG
m_ctxpool_mutex->Enter();
if (!m_objpool_debug) m_objpool_debug = new WDL_PtrList<HGDIOBJ__>;
if (m_objpool_debug->GetSize()>8192)
{
p = m_objpool_debug->Get(0);
m_objpool_debug->Delete(0);
memset(p,0,sizeof(*p));
}
m_ctxpool_mutex->Leave();
#else
if (m_objpool)
{
m_ctxpool_mutex->Enter();
if ((p=m_objpool))
{
m_objpool = p->_next;
m_objpool_size--;
memset(p,0,sizeof(*p));
}
m_ctxpool_mutex->Leave();
}
#endif
if (!p)
{
// printf("alloc obj\n");
p=(HGDIOBJ__ *)calloc(sizeof(HGDIOBJ__),1);
}
return p;
}
static bool HGDIOBJ_VALID(HGDIOBJ__ *p, int reqType=0)
{
return p &&
WDL_NORMALLY( p != (HGDIOBJ__*)TYPE_PEN && p != (HGDIOBJ__*)TYPE_BRUSH &&
p != (HGDIOBJ__*)TYPE_FONT && p != (HGDIOBJ__*)TYPE_BITMAP) &&
WDL_NORMALLY(!p->_infreelist) &&
WDL_NORMALLY(!reqType || reqType == p->type);
}
static void GDP_OBJECT_DELETE(HGDIOBJ__ *p)
{
if (!m_ctxpool_mutex) m_ctxpool_mutex=new WDL_Mutex;
if (WDL_NOT_NORMALLY(!p) || !HGDIOBJ_VALID(p)) return;
memset(p,0,sizeof(*p));
#ifdef SWELL_GDI_DEBUG
m_ctxpool_mutex->Enter();
p->_infreelist = true;
if (!m_objpool_debug) m_objpool_debug = new WDL_PtrList<HGDIOBJ__>;
m_objpool_debug->Add(p);
m_ctxpool_mutex->Leave();
#else
if (m_objpool_size<200)
{
m_ctxpool_mutex->Enter();
p->_infreelist = true;
p->_next = m_objpool;
m_objpool = p;
m_objpool_size++;
m_ctxpool_mutex->Leave();
}
else
{
// printf("free obj\n");
free(p);
}
#endif
}
static bool HDC_VALID(HDC__ *ct)
{
return ct && WDL_NORMALLY(!ct->_infreelist);
}
#if !defined(SWELL_GDI_DEBUG) && defined(SWELL_CLEANUP_ON_UNLOAD)
class _swellGdiUnloader
{
public:
_swellGdiUnloader() { }
~_swellGdiUnloader()
{
{
HDC__ *p = m_ctxpool;
m_ctxpool = NULL;
while (p)
{
HDC__ *t = p;
p = p->_next;
free(t);
}
}
{
HGDIOBJ__ *p = m_objpool;
m_objpool = NULL;
while (p)
{
HGDIOBJ__ *t = p;
p = p->_next;
free(t);
}
}
delete m_ctxpool_mutex;
m_ctxpool_mutex=NULL;
}
};
_swellGdiUnloader __swell__swellGdiUnloader;
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#ifndef SWELL_TARGET_GDK
#include "swell-internal.h"
#include "swell-dlggen.h"
#include "../wdlcstring.h"
void swell_oswindow_destroy(HWND hwnd)
{
if (hwnd && hwnd->m_oswindow)
{
if (SWELL_focused_oswindow == hwnd->m_oswindow) SWELL_focused_oswindow = NULL;
hwnd->m_oswindow=NULL;
#ifdef SWELL_LICE_GDI
delete hwnd->m_backingstore;
hwnd->m_backingstore=0;
#endif
}
}
void swell_oswindow_update_text(HWND hwnd)
{
if (hwnd) printf("SWELL: swt '%s'\n",hwnd->m_title.Get());
}
void swell_oswindow_focus(HWND hwnd)
{
if (!hwnd)
{
SWELL_focused_oswindow = NULL;
}
while (hwnd && !hwnd->m_oswindow) hwnd=hwnd->m_parent;
if (hwnd && hwnd->m_oswindow != SWELL_focused_oswindow)
{
SWELL_focused_oswindow = hwnd->m_oswindow;
}
}
void swell_recalcMinMaxInfo(HWND hwnd)
{
}
void SWELL_initargs(int *argc, char ***argv)
{
}
void swell_oswindow_updatetoscreen(HWND hwnd, RECT *rect)
{
}
void swell_oswindow_manage(HWND hwnd, bool wantfocus)
{
if (!hwnd) return;
bool isVis = !!hwnd->m_oswindow;
bool wantVis = !hwnd->m_parent && hwnd->m_visible;
if (isVis != wantVis)
{
if (!wantVis) swell_oswindow_destroy(hwnd);
else
{
// generic implementation
hwnd->m_oswindow = hwnd;
if (wantfocus) swell_oswindow_focus(hwnd);
}
}
if (wantVis) swell_oswindow_update_text(hwnd);
}
void SWELL_RunEvents()
{
}
void swell_oswindow_update_style(HWND hwnd, LONG oldstyle)
{
}
void swell_oswindow_update_enable(HWND hwnd)
{
}
int SWELL_SetWindowLevel(HWND hwnd, int newlevel)
{
int rv=0;
if (hwnd)
{
rv = hwnd->m_israised ? 1 : 0;
hwnd->m_israised = newlevel>0;
}
return rv;
}
void SWELL_GetViewPort(RECT *r, const RECT *sourcerect, bool wantWork)
{
r->left=r->top=0;
r->right=1024;
r->bottom=768;
}
bool GetWindowRect(HWND hwnd, RECT *r)
{
if (!hwnd) return false;
if (hwnd->m_oswindow)
{
*r = hwnd->m_position;
return true;
}
r->left=r->top=0;
ClientToScreen(hwnd,(LPPOINT)r);
r->right = r->left + hwnd->m_position.right - hwnd->m_position.left;
r->bottom = r->top + hwnd->m_position.bottom - hwnd->m_position.top;
return true;
}
void swell_oswindow_begin_resize(SWELL_OSWINDOW wnd) { }
void swell_oswindow_resize(SWELL_OSWINDOW wnd, int reposflag, RECT f) { }
void swell_oswindow_postresize(HWND hwnd, RECT f) { }
void swell_oswindow_invalidate(HWND hwnd, const RECT *r) { }
void UpdateWindow(HWND hwnd) { }
static WDL_IntKeyedArray<HANDLE> m_clip_recs(GlobalFree);
static WDL_PtrList<char> m_clip_curfmts;
bool OpenClipboard(HWND hwndDlg)
{
RegisterClipboardFormat(NULL);
return true;
}
void CloseClipboard() { }
UINT EnumClipboardFormats(UINT lastfmt)
{
int x=0;
for (;;)
{
int fmt=0;
if (!m_clip_recs.Enumerate(x++,&fmt)) return 0;
if (lastfmt == 0) return fmt;
if ((UINT)fmt == lastfmt) return m_clip_recs.Enumerate(x++,&fmt) ? fmt : 0;
}
}
HANDLE GetClipboardData(UINT type)
{
return m_clip_recs.Get(type);
}
void EmptyClipboard()
{
m_clip_recs.DeleteAll();
}
void SetClipboardData(UINT type, HANDLE h)
{
if (h) m_clip_recs.Insert(type,h);
else m_clip_recs.Delete(type);
}
UINT RegisterClipboardFormat(const char *desc)
{
if (!m_clip_curfmts.GetSize())
{
m_clip_curfmts.Add(strdup("SWELL__CF_TEXT"));
m_clip_curfmts.Add(strdup("SWELL__CF_HDROP"));
}
if (!desc || !*desc) return 0;
int x;
const int n = m_clip_curfmts.GetSize();
for(x=0;x<n;x++)
if (!strcmp(m_clip_curfmts.Get(x),desc)) return x + 1;
m_clip_curfmts.Add(strdup(desc));
return n+1;
}
void GetCursorPos(POINT *pt)
{
pt->x=0;
pt->y=0;
}
WORD GetAsyncKeyState(int key)
{
return 0;
}
DWORD GetMessagePos()
{
return 0;
}
HWND SWELL_CreateXBridgeWindow(HWND viewpar, void **wref, const RECT *r)
{
*wref = NULL;
return NULL;
}
void SWELL_InitiateDragDrop(HWND hwnd, RECT* srcrect, const char* srcfn, void (*callback)(const char* dropfn))
{
}
// owner owns srclist, make copies here etc
void SWELL_InitiateDragDropOfFileList(HWND hwnd, RECT *srcrect, const char **srclist, int srccount, HICON icon)
{
}
void SWELL_FinishDragDrop() { }
static HCURSOR m_last_setcursor;
void SWELL_SetCursor(HCURSOR curs)
{
m_last_setcursor=curs;
}
HCURSOR SWELL_GetCursor()
{
return m_last_setcursor;
}
HCURSOR SWELL_GetLastSetCursor()
{
return m_last_setcursor;
}
static int m_curvis_cnt;
bool SWELL_IsCursorVisible()
{
return m_curvis_cnt>=0;
}
int SWELL_ShowCursor(BOOL bShow)
{
m_curvis_cnt += (bShow?1:-1);
return m_curvis_cnt;
}
BOOL SWELL_SetCursorPos(int X, int Y)
{
return false;
}
HCURSOR SWELL_LoadCursorFromFile(const char *fn)
{
return NULL;
}
static SWELL_CursorResourceIndex *SWELL_curmodule_cursorresource_head;
HCURSOR SWELL_LoadCursor(const char *_idx)
{
return NULL;
}
void SWELL_Register_Cursor_Resource(const char *idx, const char *name, int hotspot_x, int hotspot_y)
{
SWELL_CursorResourceIndex *ri = (SWELL_CursorResourceIndex*)malloc(sizeof(SWELL_CursorResourceIndex));
ri->hotspot.x = hotspot_x;
ri->hotspot.y = hotspot_y;
ri->resname=name;
ri->cachedCursor=0;
ri->resid = idx;
ri->_next = SWELL_curmodule_cursorresource_head;
SWELL_curmodule_cursorresource_head = ri;
}
int SWELL_KeyToASCII(int wParam, int lParam, int *newflags)
{
return 0;
}
int swell_is_app_inactive() { return 0; }
void *SWELL_GetOSWindow(HWND hwnd, const char *type) { return NULL; }
void *SWELL_GetOSEvent(const char *type) { return NULL; }
#endif
#endif

View File

@@ -0,0 +1,634 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file implements basic win32 GetPrivateProfileString / etc support.
It works by caching reads, but writing through on every write that is required (to ensure
that updates take, especially when being updated from multiple modules who have their own
cache of the .ini file).
It is threadsafe, but in theory if two processes are trying to access the same ini,
results may go a bit unpredictable (but in general the file should NOT get corrupted,
we hope).
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "../assocarray.h"
#include "../wdlcstring.h"
#include "../mutex.h"
#include "../queue.h"
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/types.h>
static void deleteStringKeyedArray(WDL_StringKeyedArray<char *> *p) { delete p; }
struct iniFileContext
{
iniFileContext() : m_sections(false,deleteStringKeyedArray)
{
m_curfn=NULL;
m_lastaccesscnt=0;
m_curfn_time=0;
m_curfn_sz=0;
}
~iniFileContext() { }
WDL_UINT64 m_lastaccesscnt;
time_t m_curfn_time;
int m_curfn_sz;
char *m_curfn;
WDL_StringKeyedArray< WDL_StringKeyedArray<char *> * > m_sections;
};
#define NUM_OPEN_CONTEXTS 32
static iniFileContext s_ctxs[NUM_OPEN_CONTEXTS];
static WDL_Mutex m_mutex;
static time_t getfileupdtimesize(const char *fn, int *szOut)
{
struct stat st;
*szOut = 0;
if (!fn || !fn[0] || stat(fn,&st)) return 0;
if (S_ISLNK(st.st_mode))
{
char *linkpath = realpath(fn,NULL);
if (linkpath)
{
const bool ok = !stat(linkpath,&st);
free(linkpath);
if (!ok) return 0;
}
}
*szOut = (int)st.st_size;
return st.st_mtime;
}
static bool fgets_to_typedbuf(WDL_TypedBuf<char> *buf, FILE *fp)
{
int rdpos=0;
while (rdpos < 1024*1024*32)
{
if (buf->GetSize()<rdpos+8192) buf->Resize(rdpos+8192);
if (buf->GetSize()<rdpos+4) break; // malloc fail, erg
char *p = buf->Get()+rdpos;
*p=0;
if (!fgets(p,buf->GetSize()-rdpos,fp) || !*p) break;
while (*p) p++;
if (p[-1] == '\r' || p[-1] == '\n') break;
rdpos = (int) (p - buf->Get());
}
return buf->GetSize()>0 && buf->Get()[0];
}
// return true on success
static iniFileContext *GetFileContext(const char *name)
{
static WDL_UINT64 acc_cnt;
int best_z = 0;
char fntemp[512];
if (!name || !strstr(name,"/"))
{
extern char *g_swell_defini;
if (g_swell_defini)
{
lstrcpyn_safe(fntemp,g_swell_defini,sizeof(fntemp));
}
else
{
const char *p = getenv("HOME");
snprintf(fntemp,sizeof(fntemp),"%s/.libSwell.ini",
p && *p ? p : "/tmp");
}
if (name && *name)
{
WDL_remove_fileext(fntemp);
snprintf_append(fntemp,sizeof(fntemp),"_%s%s",name,
stricmp(WDL_get_fileext(name),".ini")?".ini":"");
}
name = fntemp;
}
{
int w;
WDL_UINT64 bestcnt = 0;
bestcnt--;
for (w=0;w<NUM_OPEN_CONTEXTS;w++)
{
if (!s_ctxs[w].m_curfn || !stricmp(s_ctxs[w].m_curfn,name))
{
// we never clear m_curfn, so we'll always find an item in cache before an unused cache entry
best_z=w;
break;
}
if (s_ctxs[w].m_lastaccesscnt < bestcnt) { best_z = w; bestcnt = s_ctxs[w].m_lastaccesscnt; }
}
}
iniFileContext *ctx = &s_ctxs[best_z];
ctx->m_lastaccesscnt=++acc_cnt;
int sz=0;
if (!ctx->m_curfn || stricmp(ctx->m_curfn,name) || ctx->m_curfn_time != getfileupdtimesize(ctx->m_curfn,&sz) || sz != ctx->m_curfn_sz)
{
ctx->m_sections.DeleteAll();
// printf("reinitting to %s\n",name);
if (!ctx->m_curfn || stricmp(ctx->m_curfn,name))
{
free(ctx->m_curfn);
ctx->m_curfn=strdup(name);
}
FILE *fp = WDL_fopenA(name,"r");
if (!fp)
{
ctx->m_curfn_time=0;
ctx->m_curfn_sz=0;
return ctx; // allow to proceed (empty file)
}
flock(fileno(fp),LOCK_SH);
// parse .ini file
WDL_StringKeyedArray<char *> *cursec=NULL;
int lcnt=0;
for (;;)
{
static WDL_TypedBuf<char> _buf;
if (!fgets_to_typedbuf(&_buf,fp)) break;
char *buf = _buf.Get();
if (!ctx->m_sections.GetSize())
{
lcnt += strlen(buf);
if (lcnt > 256*1024) break; // dont bother reading more than 256kb if no section encountered
}
char *p=buf;
while (*p) p++;
if (p>buf)
{
p--;
while (p >= buf && (*p==' ' || *p == '\r' || *p == '\n' || *p == '\t')) p--;
p[1]=0;
}
p=buf;
while (*p == ' ' || *p == '\t') p++;
if (p[0] == '[')
{
char *p2=p;
while (*p2 && *p2 != ']') p2++;
if (*p2)
{
*p2=0;
if (cursec) cursec->Resort();
if (p[1])
{
cursec = ctx->m_sections.Get(p+1);
if (!cursec)
{
cursec = new WDL_StringKeyedArray<char *>(false,WDL_StringKeyedArray<char *>::freecharptr);
ctx->m_sections.Insert(p+1,cursec);
}
else cursec->DeleteAll();
}
else cursec=0;
}
}
else if (cursec)
{
char *t=strstr(p,"=");
if (t)
{
*t++=0;
// for maximum win32 compat, we should skip leading whitespace on t, and also trim quotes if any
WDL_remove_trailing_whitespace(p);
if (*p)
cursec->AddUnsorted(p,strdup(t));
}
}
}
ctx->m_curfn_time = getfileupdtimesize(name,&ctx->m_curfn_sz);
flock(fileno(fp),LOCK_UN);
fclose(fp);
if (cursec) cursec->Resort();
}
return ctx;
}
static void WriteBackFile(iniFileContext *ctx)
{
if (!ctx||!ctx->m_curfn) return;
char newfn[1024];
const char *curfn = ctx->m_curfn;
struct stat st;
char *needfree = NULL;
if (!stat(curfn,&st) && S_ISLNK(st.st_mode))
{
needfree = realpath(curfn,NULL);
if (needfree) curfn = needfree;
}
lstrcpyn_safe(newfn,curfn,sizeof(newfn)-8);
{
char *p=newfn;
while (*p) p++;
while (p>newfn && p[-1] != '/') p--;
char lc = '.';
while (*p)
{
char c = *p;
*p++ = lc;
lc = c;
}
*p++ = lc;
strcpy(p,".new");
}
FILE *fp = WDL_fopenA(newfn,"w");
if (!fp)
{
free(needfree);
return;
}
flock(fileno(fp),LOCK_EX);
int x;
for (x = 0; ; x ++)
{
const char *secname=NULL;
WDL_StringKeyedArray<char *> * cursec = ctx->m_sections.Enumerate(x,&secname);
if (!cursec || !secname) break;
fprintf(fp,"[%s]\n",secname);
int y;
for (y=0;;y++)
{
const char *keyname = NULL;
const char *keyvalue = cursec->Enumerate(y,&keyname);
if (!keyvalue || !keyname) break;
if (*keyname) fprintf(fp,"%s=%s\n",keyname,keyvalue);
}
fprintf(fp,"\n");
}
fflush(fp);
flock(fileno(fp),LOCK_UN);
fclose(fp);
if (!rename(newfn,curfn))
{
ctx->m_curfn_time = getfileupdtimesize(curfn,&ctx->m_curfn_sz);
}
else
{
// error updating, hmm how to handle this?
}
free(needfree);
}
BOOL WritePrivateProfileSection(const char *appname, const char *strings, const char *fn)
{
if (!appname) return FALSE;
WDL_MutexLock lock(&m_mutex);
iniFileContext *ctx = GetFileContext(fn);
if (!ctx) return FALSE;
WDL_StringKeyedArray<char *> * cursec = ctx->m_sections.Get(appname);
if (!cursec)
{
if (!*strings) return TRUE;
cursec = new WDL_StringKeyedArray<char *>(false,WDL_StringKeyedArray<char *>::freecharptr);
ctx->m_sections.Insert(appname,cursec);
}
else cursec->DeleteAll();
if (*strings)
{
while (*strings)
{
char buf[8192];
lstrcpyn_safe(buf,strings,sizeof(buf));
char *p = buf;
while (*p && *p != '=') p++;
if (*p)
{
*p++=0;
cursec->Insert(buf,strdup(strings + (p-buf)));
}
strings += strlen(strings)+1;
}
}
WriteBackFile(ctx);
return TRUE;
}
BOOL WritePrivateProfileString(const char *appname, const char *keyname, const char *val, const char *fn)
{
if (!appname || (keyname && !*keyname)) return FALSE;
// printf("writing %s %s %s %s\n",appname,keyname,val,fn);
WDL_MutexLock lock(&m_mutex);
iniFileContext *ctx = GetFileContext(fn);
if (!ctx) return FALSE;
if (!keyname)
{
if (ctx->m_sections.Get(appname))
{
ctx->m_sections.Delete(appname);
WriteBackFile(ctx);
}
}
else
{
WDL_StringKeyedArray<char *> * cursec = ctx->m_sections.Get(appname);
if (!val)
{
if (cursec && cursec->Get(keyname))
{
cursec->Delete(keyname);
WriteBackFile(ctx);
}
}
else
{
const char *p;
if (!cursec || !(p=cursec->Get(keyname)) || strcmp(p,val))
{
if (!cursec)
{
cursec = new WDL_StringKeyedArray<char *>(false,WDL_StringKeyedArray<char *>::freecharptr);
ctx->m_sections.Insert(appname,cursec);
}
cursec->Insert(keyname,strdup(val));
WriteBackFile(ctx);
}
}
}
return TRUE;
}
static void lstrcpyn_trimmed(char* dest, const char* src, int len)
{
if (len<1) return;
// Mimic Win32 behavior of stripping quotes and whitespace
while (*src==' ' || *src=='\t') ++src; // Strip beginning whitespace
const char *end = src;
if (*end) while (end[1]) end++;
while (end >= src && (*end==' ' || *end=='\t')) --end; // Strip end whitespace
if (end > src && ((*src=='\"' && *end=='\"') || (*src=='\'' && *end=='\'')))
{
// Strip initial set of "" or ''
++src;
--end;
}
int newlen = (int) (end-src+2);
if (newlen < 1) newlen = 1;
else if (newlen > len) newlen = len;
lstrcpyn_safe(dest, src, newlen);
}
DWORD GetPrivateProfileSection(const char *appname, char *strout, DWORD strout_len, const char *fn)
{
WDL_MutexLock lock(&m_mutex);
if (!strout || strout_len<2)
{
if (strout && strout_len==1) *strout=0;
return 0;
}
iniFileContext *ctx= GetFileContext(fn);
int szOut=0;
WDL_StringKeyedArray<char *> *cursec = ctx ? ctx->m_sections.Get(appname) : NULL;
if (ctx && cursec)
{
int x;
for(x=0;x<cursec->GetSize();x++)
{
const char *kv = NULL;
const char *val = cursec->Enumerate(x,&kv);
if (val && kv)
{
int l;
#define WRSTR(v) \
l = (int)strlen(v); \
if (l > (int)strout_len - szOut - 2) l = (int)strout_len - 2 - szOut; \
if (l>0) { memcpy(strout+szOut,v,l); szOut+=l; }
WRSTR(kv)
WRSTR("=")
#undef WRSTR
lstrcpyn_trimmed(strout+szOut, val, (int)strout_len - szOut - 2);
szOut += strlen(strout+szOut);
l=1;
if (l > (int)strout_len - szOut - 1) l = (int)strout_len - 1 - szOut;
if (l>0) { memset(strout+szOut,0,l); szOut+=l; }
if (szOut >= (int)strout_len-1)
{
strout[strout_len-1]=0;
return strout_len-2;
}
}
}
}
strout[szOut]=0;
if (!szOut) strout[1]=0;
return szOut;
}
DWORD GetPrivateProfileString(const char *appname, const char *keyname, const char *def, char *ret, int retsize, const char *fn)
{
WDL_MutexLock lock(&m_mutex);
// printf("getprivateprofilestring: %s\n",fn);
iniFileContext *ctx= GetFileContext(fn);
if (ctx)
{
if (!appname||!keyname)
{
WDL_Queue tmpbuf;
if (!appname)
{
int x;
for (x = 0;; x ++)
{
const char *secname=NULL;
if (!ctx->m_sections.Enumerate(x,&secname) || !secname) break;
if (*secname) tmpbuf.Add(secname,(int)strlen(secname)+1);
}
}
else
{
WDL_StringKeyedArray<char *> *cursec = ctx->m_sections.Get(appname);
if (cursec)
{
int y;
for (y = 0; ; y ++)
{
const char *k=NULL;
if (!cursec->Enumerate(y,&k)||!k) break;
if (*k) tmpbuf.Add(k,(int)strlen(k)+1);
}
}
}
int sz=tmpbuf.GetSize()-1;
if (sz<0)
{
ret[0]=ret[1]=0;
return 0;
}
if (sz > retsize-2) sz=retsize-2;
memcpy(ret,tmpbuf.Get(),sz);
ret[sz]=ret[sz+1]=0;
return (DWORD)sz;
}
WDL_StringKeyedArray<char *> *cursec = ctx->m_sections.Get(appname);
if (cursec)
{
const char *val = cursec->Get(keyname);
if (val)
{
lstrcpyn_trimmed(ret,val,retsize);
return (DWORD)strlen(ret);
}
}
}
// printf("def %s %s %s %s\n",appname,keyname,def,fn);
lstrcpyn_safe(ret,def?def:"",retsize);
return (DWORD)strlen(ret);
}
int GetPrivateProfileInt(const char *appname, const char *keyname, int def, const char *fn)
{
char buf[512];
GetPrivateProfileString(appname,keyname,"",buf,sizeof(buf),fn);
if (buf[0])
{
int a=atoi(buf);
if (a||buf[0]=='0') return a;
}
return def;
}
static bool __readbyte(char *src, unsigned char *out)
{
unsigned char cv=0;
int s=4;
while(s>=0)
{
if (*src >= '0' && *src <= '9') cv += (*src-'0')<<s;
else if (*src >= 'a' && *src <= 'f') cv += (*src-'a' + 10)<<s;
else if (*src >= 'A' && *src <= 'F') cv += (*src-'A' + 10)<<s;
else return false;
src++;
s-=4;
}
*out=cv;
return true;
}
BOOL GetPrivateProfileStruct(const char *appname, const char *keyname, void *buf, int bufsz, const char *fn)
{
if (!appname || !keyname || bufsz<0) return 0;
char *tmp=(char *)malloc((bufsz+1)*2+16);
if (!tmp) return 0;
BOOL ret=0;
GetPrivateProfileString(appname,keyname,"",tmp,(bufsz+1)*2+15,fn);
if (strlen(tmp) == (size_t) (bufsz+1)*2)
{
unsigned char sum=0;
unsigned char *bufout=(unsigned char *)buf;
char *src=tmp;
unsigned char cv;
while (bufsz-->0)
{
if (!__readbyte(src,&cv)) break;
*bufout++ = cv;
sum += cv;
src+=2;
}
ret = bufsz<0 && __readbyte(src,&cv) && cv==sum;
}
free(tmp);
//printf("getprivateprofilestruct returning %d\n",ret);
return ret;
}
BOOL WritePrivateProfileStruct(const char *appname, const char *keyname, const void *buf, int bufsz, const char *fn)
{
if (!keyname || !buf) return WritePrivateProfileString(appname,keyname,(const char *)buf,fn);
char *tmp=(char *)malloc((bufsz+1)*2+1);
if (!tmp) return 0;
char *p = tmp;
unsigned char sum=0;
unsigned char *src=(unsigned char *)buf;
while (bufsz-- > 0)
{
sprintf(p,"%02X",*src);
sum+=*src++;
p+=2;
}
sprintf(p,"%02X",sum);
BOOL ret=WritePrivateProfileString(appname,keyname,tmp,fn);
free(tmp);
return ret;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides basic key and mouse cursor querying, as well as a key to windows key translation function.
*/
// everything has moved to swell-generic-*.cpp

View File

@@ -0,0 +1,693 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides basic key and mouse cursor querying, as well as a mac key to windows key translation function.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "swell-dlggen.h"
#include "../wdltypes.h"
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
static int MacKeyCodeToVK(int code, int *flag)
{
switch (code)
{
case 51: return VK_BACK;
case 65: return VK_DECIMAL;
case 67: return VK_MULTIPLY;
case 69: return VK_ADD;
case 71: return VK_NUMLOCK;
case 75: return VK_DIVIDE;
case 76: *flag |= 1<<24; return VK_RETURN;
case 78: return VK_SUBTRACT;
case 81: return VK_SEPARATOR;
case 82: return VK_NUMPAD0;
case 83: return VK_NUMPAD1;
case 84: return VK_NUMPAD2;
case 85: return VK_NUMPAD3;
case 86: return VK_NUMPAD4;
case 87: return VK_NUMPAD5;
case 88: return VK_NUMPAD6;
case 89: return VK_NUMPAD7;
case 91: return VK_NUMPAD8;
case 92: return VK_NUMPAD9;
case 96: return VK_F5;
case 97: return VK_F6;
case 98: return VK_F7;
case 99: return VK_F3;
case 100: return VK_F8;
case 101: return VK_F9;
case 109: return VK_F10;
case 103: return VK_F11;
case 111: return VK_F12;
case 114: *flag |= 1<<24; return VK_INSERT;
case 115: *flag |= 1<<24; return VK_HOME;
case 117: *flag |= 1<<24; return VK_DELETE;
case 116: *flag |= 1<<24; return VK_PRIOR;
case 118: return VK_F4;
case 119: *flag |= 1<<24; return VK_END;
case 120: return VK_F2;
case 121: *flag |= 1<<24; return VK_NEXT;
case 122: return VK_F1;
case 123: *flag |= 1<<24; return VK_LEFT;
case 124: *flag |= 1<<24; return VK_RIGHT;
case 125: *flag |= 1<<24; return VK_DOWN;
case 126: *flag |= 1<<24; return VK_UP;
case 0x69: return VK_F13;
case 0x6B: return VK_F14;
case 0x71: return VK_F15;
case 0x6A: return VK_F16;
}
return 0;
}
bool IsRightClickEmulateEnabled();
#ifdef MAC_OS_X_VERSION_10_5
static int charFromVcode(int keyCode) // used for getting the root char (^, `) from dead keys on other keyboards,
// only used when using MacKeyToWindowsKeyEx() with mode=1, for now
{
static char loaded;
static TISInputSourceRef (*_TISCopyCurrentKeyboardInputSource)( void);
static void* (*_TISGetInputSourceProperty) ( TISInputSourceRef inputSource, CFStringRef propertyKey);
if (!loaded)
{
loaded++;
CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
if (b)
{
*(void **)&_TISGetInputSourceProperty = CFBundleGetFunctionPointerForName(b,CFSTR("TISGetInputSourceProperty"));
*(void **)&_TISCopyCurrentKeyboardInputSource = CFBundleGetFunctionPointerForName(b,CFSTR("TISCopyCurrentKeyboardInputSource"));
}
}
if (!_TISCopyCurrentKeyboardInputSource || !_TISGetInputSourceProperty) return 0;
TISInputSourceRef currentKeyboard = _TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)_TISGetInputSourceProperty(currentKeyboard, CFSTR("TISPropertyUnicodeKeyLayoutData"));
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
if(keyboardLayout)
{
UInt32 deadKeyState = 0;
UniCharCount maxStringLength = 255;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];
OSStatus status = UCKeyTranslate(keyboardLayout,
keyCode, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
if (actualStringLength == 0 && deadKeyState)
{
status = UCKeyTranslate(keyboardLayout,
kVK_Space, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
}
if(actualStringLength > 0 && status == noErr) return unicodeString[0];
}
return 0;
}
#endif
int SWELL_MacKeyToWindowsKeyEx(void *nsevent, int *flags, int mode)
{
NSEvent *theEvent = (NSEvent *)nsevent;
if (!theEvent) theEvent = [NSApp currentEvent];
const NSInteger mod=[theEvent modifierFlags];
int flag=0;
if (mod & NSShiftKeyMask) flag|=FSHIFT;
if (mod & NSCommandKeyMask) flag|=FCONTROL; // todo: this should be command once we figure it out
if (mod & NSAlternateKeyMask) flag|=FALT;
if ((mod&NSControlKeyMask) && !IsRightClickEmulateEnabled()) flag|=FLWIN;
int rawcode=[theEvent keyCode];
int code=MacKeyCodeToVK(rawcode,&flag);
if (!code)
{
NSString *str=NULL;
if (mode == 1) str=[theEvent characters];
if (!str || ![str length]) str=[theEvent charactersIgnoringModifiers];
if (!str || ![str length])
{
#ifdef MAC_OS_X_VERSION_10_5
if (mode==1) code=charFromVcode(rawcode);
#endif
if (!code)
{
code = 1024+rawcode; // raw code
flag|=FVIRTKEY;
}
}
else
{
code=[str characterAtIndex:0];
if (code >= NSF1FunctionKey && code <= NSF24FunctionKey)
{
flag|=FVIRTKEY;
code += VK_F1 - NSF1FunctionKey;
}
else
{
if (code >= 'a' && code <= 'z') code+='A'-'a';
if (code == 25 && (flag&FSHIFT)) code=VK_TAB;
if (isalnum(code)||code==' ' || code == '\r' || code == '\n' || code ==27 || code == VK_TAB) flag|=FVIRTKEY;
}
}
}
else
{
flag|=FVIRTKEY;
if (code==8) code='\b';
}
if (!(flag&FVIRTKEY)) flag&=~FSHIFT;
if (flags) *flags=flag;
return code;
}
int SWELL_MacKeyToWindowsKey(void *nsevent, int *flags)
{
if (!nsevent) return 0;
return SWELL_MacKeyToWindowsKeyEx(nsevent,flags,0);
}
int SWELL_KeyToASCII(int wParam, int lParam, int *newflags)
{
if (wParam >= '0' && wParam <= '9' && lParam == (FSHIFT|FVIRTKEY))
{
*newflags = lParam&~(FSHIFT|FVIRTKEY);
if (!(lParam & (FCONTROL|FLWIN))) switch (wParam)
{
case '1': return '!';
case '2': return '@';
case '3': return '#';
case '4': return '$';
case '5': return '%';
case '6': return '^';
case '7': return '&';
case '8': return '*';
case '9': return '(';
case '0': return ')';
}
}
return 0;
}
WORD GetAsyncKeyState(int key)
{
CGEventFlags state=0;
if (key == VK_LBUTTON || key == VK_RBUTTON || key == VK_MBUTTON)
{
state=GetCurrentEventButtonState();
}
else
{
state=CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState);
}
if ((key == VK_LBUTTON && (state&1)) ||
(key == VK_RBUTTON && (state&2)) ||
(key == VK_MBUTTON && (state&4)) ||
(key == VK_SHIFT && (state&kCGEventFlagMaskShift)) ||
(key == VK_CONTROL && (state&kCGEventFlagMaskCommand)) ||
(key == VK_MENU && (state&kCGEventFlagMaskAlternate)) ||
(key == VK_LWIN && !IsRightClickEmulateEnabled() && (state&kCGEventFlagMaskControl)))
{
return 0x8000;
}
return 0;
}
static SWELL_CursorResourceIndex *SWELL_curmodule_cursorresource_head;
static NSCursor* MakeCursorFromData(unsigned char* data, int hotspot_x, int hotspot_y)
{
NSCursor *c=NULL;
NSBitmapImageRep* bmp = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:0
pixelsWide:16
pixelsHigh:16
bitsPerSample:8
samplesPerPixel:2
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedWhiteColorSpace
bytesPerRow:(16*2)
bitsPerPixel:16];
if (bmp)
{
unsigned char* p = [bmp bitmapData];
if (p)
{
int i;
for (i = 0; i < 16*16; ++i)
{
// tried 4 bits per sample and memcpy, didn't work
p[2*i] = (data[i]&0xF0) | data[i]>>4;
p[2*i+1] = (data[i]<<4) | (data[i]&0xf);
}
NSImage *img = [[NSImage alloc] init];
if (img)
{
[img addRepresentation:bmp];
NSPoint hs = NSMakePoint(hotspot_x, hotspot_y);
c = [[NSCursor alloc] initWithImage:img hotSpot:hs];
[img release];
}
}
[bmp release];
}
return c;
}
static NSCursor* MakeSWELLSystemCursor(const char *id)
{
// bytemaps are (white<<4)|(alpha)
const unsigned char B = 0xF;
const unsigned char W = 0xFF;
const unsigned char G = 0xF8;
static NSCursor* carr[4] = { 0, 0, 0, 0 };
NSCursor** pc=0;
if (id == IDC_SIZEALL) pc = &carr[0];
else if (id == IDC_SIZENWSE) pc = &carr[1];
else if (id == IDC_SIZENESW) pc = &carr[2];
else if (id == IDC_NO) pc = &carr[3];
else return 0;
if (!(*pc))
{
if (id == IDC_SIZEALL)
{
static unsigned char p[16*16] =
{
0, 0, 0, 0, 0, 0, G, W, W, G, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, G, W, B, B, W, G, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, W, B, B, B, B, W, 0, 0, 0, 0, 0,
0, 0, 0, 0, G, B, B, B, B, B, B, G, 0, 0, 0, 0,
0, 0, 0, G, 0, 0, W, B, B, W, 0, 0, G, 0, 0, 0,
0, G, W, B, 0, 0, W, B, B, W, 0, 0, B, W, G, 0,
G, W, B, B, W, W, W, B, B, W, W, W, B, B, W, G,
W, B, B, B, B, B, B, B, B, B, B, B, B, B, B, W,
W, B, B, B, B, B, B, B, B, B, B, B, B, B, B, W,
G, W, B, B, W, W, W, B, B, W, W, W, B, B, W, G,
0, G, W, B, 0, 0, W, B, B, W, 0, 0, B, W, G, 0,
0, 0, 0, G, 0, 0, W, B, B, W, 0, 0, G, 0, 0, 0,
0, 0, 0, 0, G, B, B, B, B, B, B, G, 0, 0, 0, 0,
0, 0, 0, 0, 0, W, B, B, B, B, W, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, G, W, B, B, W, G, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, G, W, W, G, 0, 0, 0, 0, 0, 0,
};
*pc = MakeCursorFromData(p, 8, 8);
}
else if (id == IDC_SIZENWSE || id == IDC_SIZENESW)
{
static unsigned char p[16*16] =
{
W, W, W, W, W, W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
W, G, G, G, W, G, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
W, G, B, W, G, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
W, G, W, B, W, G, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
W, W, G, W, B, W, G, 0, 0, 0, 0, 0, 0, 0, 0, 0,
W, G, 0, G, W, B, W, G, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, G, W, B, W, G, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, G, W, B, W, G, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, G, W, B, W, G, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, G, W, B, W, G, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, G, W, B, W, G, 0, G, W,
0, 0, 0, 0, 0, 0, 0, 0, 0, G, W, B, W, G, W, W,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, G, W, B, W, G, W,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, G, W, B, G, W,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, G, W, G, G, G, W,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, W, W, W, W, W, W,
};
if (id == IDC_SIZENESW)
{
int x, y;
for (y = 0; y < 16; ++y)
{
for (x = 0; x < 8; ++x)
{
unsigned char tmp = p[16*y+x];
p[16*y+x] = p[16*y+16-x-1];
p[16*y+16-x-1] = tmp;
}
}
}
*pc = MakeCursorFromData(p, 8, 8);
if (id == IDC_SIZENESW) // swap back!
{
int x, y;
for (y = 0; y < 16; ++y)
{
for (x = 0; x < 8; ++x)
{
unsigned char tmp = p[16*y+x];
p[16*y+x] = p[16*y+16-x-1];
p[16*y+16-x-1] = tmp;
}
}
}
}
else if (id == IDC_NO)
{
static unsigned char p[16*16] =
{
0, 0, 0, 0, G, W, W, W, W, W, W, G, 0, 0, 0, 0,
0, 0, G, W, W, B, B, B, B, B, B, W, W, G, 0, 0,
0, G, W, B, B, B, W, W, W, W, B, B, B, W, G, 0,
0, W, B, B, W, W, G, 0, 0, G, W, G, B, B, W, 0,
G, W, B, W, G, 0, 0, 0, 0, G, W, B, G, B, W, G,
W, B, B, W, 0, 0, 0, 0, G, W, B, W, W, B, B, W,
W, B, W, G, 0, 0, 0, G, W, B, W, G, G, W, B, W,
W, B, W, 0, 0, 0, G, W, B, W, G, 0, 0, W, B, W,
W, B, W, 0, 0, G, W, B, W, G, 0, 0, 0, W, B, W,
W, B, W, G, G, W, B, W, G, 0, 0, 0, G, W, B, W,
W, B, B, W, W, B, W, G, 0, 0, 0, 0, W, B, B, W,
G, W, B, G, B, W, G, 0, 0, 0, 0, G, W, B, W, G,
0, W, B, B, G, W, G, 0, 0, G, W, W, B, B, W, 0,
0, G, W, B, B, B, W, W, W, W, B, B, B, W, G, 0,
0, 0, G, W, W, B, B, B, B, B, B, W, W, G, 0, 0,
0, 0, 0, 0, G, W, W, W, W, W, W, G, 0, 0, 0, 0,
};
*pc = MakeCursorFromData(p, 8, 8);
}
}
return *pc;
}
static NSImage *swell_imageFromCursorString(const char *name, POINT *hotSpot)
{
NSImage *img=NULL;
FILE *fp = NULL;
bool isFullFn=false;
if (!strstr(name,"/") && strlen(name)<1024)
{
char tmpn[4096];
GetModuleFileName(NULL,tmpn,(DWORD)(sizeof(tmpn)-128-strlen(name)));
strcat(tmpn,"/Contents/Resources/");
strcat(tmpn,name);
strcat(tmpn,".cur");
fp = WDL_fopenA(tmpn,"rb");
}
else
{
isFullFn=true;
if (strlen(name)>4 && !stricmp(name+strlen(name)-4,".cur")) fp = WDL_fopenA(name,"rb");
}
if (fp)
{
unsigned char buf[4096];
if (fread(buf,1,6,fp)==6 && !buf[0] && !buf[1] && buf[2] == 2 && buf[3] == 0 && buf[4] == 1 && buf[5] == 0)
{
static char tempfn[512];
if (!tempfn[0])
{
GetTempPath(256,tempfn);
snprintf(tempfn+strlen(tempfn),256,"swellcur%x%x.ico", timeGetTime(),(int)getpid());
}
FILE *outfp = WDL_fopenA(tempfn,"wb");
if (outfp)
{
bool wantLoad=false;
buf[2]=1; // change to .ico
fwrite(buf,1,6,outfp);
fread(buf,1,16,fp);
int xHot = buf[4]|(buf[5]<<8);
int yHot = buf[6]|(buf[7]<<8);
buf[4]=1; buf[5]=0; // 1 color plane
buf[6]=0; buf[7]=0; // 0 for pixel depth means "auto"
if (!buf[3])
{
fwrite(buf,1,16,outfp);
for (;;)
{
size_t a = fread(buf,1,sizeof(buf),fp);
if (a<1) break;
fwrite(buf,1,a,outfp);
}
wantLoad=true;
}
fclose(outfp);
if (wantLoad)
{
NSString *str = (NSString *)SWELL_CStringToCFString(tempfn);
img = [[NSImage alloc] initWithContentsOfFile:str];
[str release];
if (img && hotSpot)
{
hotSpot->x = xHot;
hotSpot->y = yHot;
}
// printf("loaded converted ico for %s %s %d\n",tempfn,name,!!img);
}
unlink(tempfn);
}
}
fclose(fp);
}
if (!img) // fall back
{
NSString *str = (NSString *)SWELL_CStringToCFString(name);
if (isFullFn) img = [[NSImage alloc] initWithContentsOfFile:str];
else
{
img = [NSImage imageNamed:str];
if (img) [img retain];
}
[str release];
}
return img;
}
HCURSOR SWELL_LoadCursorFromFile(const char *fn)
{
POINT hotspot={0,};
NSImage *img = swell_imageFromCursorString(fn,&hotspot);
if (img)
{
HCURSOR ret=(HCURSOR)[[NSCursor alloc] initWithImage:img hotSpot:NSMakePoint(hotspot.x,hotspot.y)];
[img release];
return ret;
}
return NULL;
}
// todo: support for loading from file
HCURSOR SWELL_LoadCursor(const char *_idx)
{
if (_idx == IDC_NO||_idx==IDC_SIZENWSE || _idx == IDC_SIZENESW || _idx == IDC_SIZEALL) return (HCURSOR) MakeSWELLSystemCursor(_idx);
if (_idx == IDC_SIZEWE) return (HCURSOR)[NSCursor resizeLeftRightCursor];
if (_idx == IDC_SIZENS) return (HCURSOR)[NSCursor resizeUpDownCursor];
if (_idx == IDC_ARROW) return (HCURSOR)[NSCursor arrowCursor];
if (_idx == IDC_HAND) return (HCURSOR)[NSCursor openHandCursor];
if (_idx == IDC_UPARROW) return (HCURSOR)[NSCursor resizeUpCursor];
if (_idx == IDC_IBEAM) return (HCURSOR)[NSCursor IBeamCursor];
// search registered cursor list
SWELL_CursorResourceIndex *p = SWELL_curmodule_cursorresource_head;
while (p)
{
if (p->resid == _idx)
{
if (p->cachedCursor) return p->cachedCursor;
NSImage *img = swell_imageFromCursorString(p->resname,&p->hotspot);
if (img)
{
p->cachedCursor=(HCURSOR)[[NSCursor alloc] initWithImage:img hotSpot:NSMakePoint(p->hotspot.x,p->hotspot.y)];
[img release];
return p->cachedCursor;
}
}
p=p->_next;
}
return 0;
}
static HCURSOR m_last_setcursor;
void SWELL_SetCursor(HCURSOR curs)
{
if (curs && [(id) curs isKindOfClass:[NSCursor class]])
{
m_last_setcursor=curs;
[(NSCursor *)curs set];
}
else
{
m_last_setcursor=NULL;
[[NSCursor arrowCursor] set];
}
}
HCURSOR SWELL_GetCursor()
{
return (HCURSOR)[NSCursor currentCursor];
}
HCURSOR SWELL_GetLastSetCursor()
{
return m_last_setcursor;
}
static POINT g_swell_mouse_relmode_curpos; // stored in osx-native coordinates (y=0=top of screen)
static bool g_swell_mouse_relmode;
void GetCursorPos(POINT *pt)
{
if (g_swell_mouse_relmode)
{
*pt=g_swell_mouse_relmode_curpos;
return;
}
NSPoint localpt=[NSEvent mouseLocation];
pt->x=(int)floor(localpt.x + 0.5);
pt->y=(int)floor(localpt.y + 0.5);
}
DWORD GetMessagePos()
{
if (g_swell_mouse_relmode)
{
return MAKELONG((int)g_swell_mouse_relmode_curpos.x,(int)g_swell_mouse_relmode_curpos.y);
}
NSPoint localpt=[NSEvent mouseLocation];
return MAKELONG((int)floor(localpt.x + 0.5), (int)floor(localpt.y + 0.5));
}
NSPoint swellProcessMouseEvent(int msg, NSView *view, NSEvent *event)
{
if (g_swell_mouse_relmode && msg==WM_MOUSEMOVE) // event will have relative coordinates
{
int idx=(int)[event deltaX];
int idy=(int)[event deltaY];
g_swell_mouse_relmode_curpos.x += idx;
g_swell_mouse_relmode_curpos.y -= idy;
}
if (g_swell_mouse_relmode)
{
POINT p=g_swell_mouse_relmode_curpos;
ScreenToClient((HWND)view,&p);
return NSMakePoint(p.x,p.y);
}
NSPoint localpt=[event locationInWindow];
return [view convertPoint:localpt fromView:nil];
}
static int m_curvis_cnt;
bool SWELL_IsCursorVisible()
{
return m_curvis_cnt>=0;
}
int SWELL_ShowCursor(BOOL bShow)
{
m_curvis_cnt += (bShow?1:-1);
if (m_curvis_cnt==-1 && !bShow)
{
GetCursorPos(&g_swell_mouse_relmode_curpos);
CGDisplayHideCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(false);
g_swell_mouse_relmode=true;
}
if (m_curvis_cnt==0 && bShow)
{
CGDisplayShowCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(true);
g_swell_mouse_relmode=false;
SetCursorPos(g_swell_mouse_relmode_curpos.x,g_swell_mouse_relmode_curpos.y);
}
return m_curvis_cnt;
}
BOOL SWELL_SetCursorPos(int X, int Y)
{
if (g_swell_mouse_relmode)
{
g_swell_mouse_relmode_curpos.x=X;
g_swell_mouse_relmode_curpos.y=Y;
return TRUE;
}
const int h = (int)CGDisplayPixelsHigh(CGMainDisplayID());
CGPoint pos=CGPointMake(X,h-Y);
return CGWarpMouseCursorPosition(pos)==kCGErrorSuccess;
}
void SWELL_Register_Cursor_Resource(const char *idx, const char *name, int hotspot_x, int hotspot_y)
{
SWELL_CursorResourceIndex *ri = (SWELL_CursorResourceIndex*)malloc(sizeof(SWELL_CursorResourceIndex));
ri->hotspot.x = hotspot_x;
ri->hotspot.y = hotspot_y;
ri->resname=name;
ri->cachedCursor=0;
ri->resid = idx;
ri->_next = SWELL_curmodule_cursorresource_head;
SWELL_curmodule_cursorresource_head = ri;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
#ifndef _SWELL_MENUGEN_H_
#define _SWELL_MENUGEN_H_
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Dynamic menu generation
Usage:
See: swell_resgen.pl etc
*/
#include "swell.h"
#ifdef BEGIN
#undef BEGIN
#endif
#ifdef END
#undef END
#endif
typedef struct SWELL_MenuResourceIndex
{
const char *resid;
void (*createFunc)(HMENU hMenu);
struct SWELL_MenuResourceIndex *_next;
} SWELL_MenuResourceIndex;
extern SWELL_MenuResourceIndex *SWELL_curmodule_menuresource_head;
#define SWELL_MENUGEN_POPUP_PREFIX "/.BO^O:"
#define SWELL_MENUGEN_ENDPOPUP "EN%%%^:"
struct SWELL_MenuGen_Entry
{
const char *name; // will begin with SWELL_MENUGEN_POPUP_PREFIX on submenus, and will be SWELL_MENUGEN_ENDPOPUP at the end of a submenu
unsigned short idx;
unsigned short flags;
};
class SWELL_MenuGenHelper
{
public:
SWELL_MenuResourceIndex m_rec;
SWELL_MenuGenHelper(SWELL_MenuResourceIndex **h, void (*cf)(HMENU), int recid)
{
m_rec.resid=MAKEINTRESOURCE(recid);
m_rec.createFunc=cf;
m_rec._next=*h;
*h = &m_rec;
}
};
#define SWELL_DEFINE_MENU_RESOURCE_BEGIN(recid) \
static void __swell_menu_cf__##recid(HMENU hMenu); \
static SWELL_MenuGenHelper __swell_menu_cf_helper__##recid(&SWELL_curmodule_menuresource_head, __swell_menu_cf__##recid, recid); \
static void __swell_menu_cf__##recid(HMENU hMenu) { static const SWELL_MenuGen_Entry list[]={{NULL,0,0
#define SWELL_DEFINE_MENU_RESOURCE_END(recid) } }; SWELL_GenerateMenuFromList(hMenu,list+1,sizeof(list)/sizeof(list[0])-1); }
#define GRAYED 1
#define INACTIVE 2
#define POPUP }, { SWELL_MENUGEN_POPUP_PREFIX
#define MENUITEM }, {
#define SEPARATOR NULL, 0xffff
#define BEGIN
#define END }, { SWELL_MENUGEN_ENDPOPUP
#endif//_SWELL_MENUGEN_H_

View File

@@ -0,0 +1,97 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "swell-internal.h"
#ifndef __APPLE__
#include <sys/types.h>
#include <sys/wait.h>
#endif
bool IsRightClickEmulateEnabled()
{
return false;
}
void SWELL_EnableRightClickEmulate(BOOL enable)
{
}
HANDLE SWELL_CreateProcessFromPID(int pid)
{
SWELL_InternalObjectHeader_PID *buf = (SWELL_InternalObjectHeader_PID*)malloc(sizeof(SWELL_InternalObjectHeader_PID));
buf->hdr.type = INTERNAL_OBJECT_PID;
buf->hdr.count = 1;
buf->pid = (int) pid;
buf->done = buf->result = 0;
return (HANDLE) buf;
}
HANDLE SWELL_CreateProcess(const char *exe, int nparams, const char **params)
{
void swell_cleanupZombies();
swell_cleanupZombies();
const pid_t pid = fork();
if (pid == 0)
{
char **pp = (char **)calloc(nparams+2,sizeof(char*));
pp[0] = strdup(exe);
for (int x=0;x<nparams;x++) pp[x+1] = strdup(params[x]?params[x]:"");
execvp(exe,pp);
exit(0);
}
if (pid < 0) return NULL;
return SWELL_CreateProcessFromPID(pid);
}
int SWELL_GetProcessExitCode(HANDLE hand)
{
SWELL_InternalObjectHeader_PID *hdr=(SWELL_InternalObjectHeader_PID*)hand;
if (!hdr || hdr->hdr.type != INTERNAL_OBJECT_PID|| !hdr->pid) return -1;
if (hdr->done) return hdr->result;
int wstatus=0;
pid_t v = waitpid((pid_t)hdr->pid,&wstatus,WNOHANG);
if (v <= 0) return -2;
hdr->done = 1;
return hdr->result = WEXITSTATUS(wstatus);
}
#ifndef SWELL_TARGET_GDK
BOOL EnumDisplayMonitors(HDC hdc,const LPRECT r,MONITORENUMPROC proc,LPARAM lParam)
{
return FALSE;
}
BOOL GetMonitorInfo(HMONITOR hmon, void *inf)
{
return FALSE;
}
#endif
#endif

View File

@@ -0,0 +1,890 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SWELL_PROVIDED_BY_APP
//#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <sys/poll.h>
#include "swell.h"
#define SWELL_IMPLEMENT_GETOSXVERSION
#include "swell-internal.h"
#include "../mutex.h"
HWND g_swell_only_timerhwnd;
@implementation SWELL_TimerFuncTarget
-(id) initWithId:(UINT_PTR)tid hwnd:(HWND)h callback:(TIMERPROC)cb
{
if ((self = [super init]))
{
m_hwnd=h;
m_cb=cb;
m_timerid = tid;
}
return self;
}
-(void)SWELL_Timer:(id)sender
{
if (g_swell_only_timerhwnd && m_hwnd != g_swell_only_timerhwnd) return;
m_cb(m_hwnd,WM_TIMER,m_timerid,GetTickCount());
}
@end
@implementation SWELL_DataHold
-(id) initWithVal:(void *)val
{
if ((self = [super init]))
{
m_data=val;
}
return self;
}
-(void *) getValue
{
return m_data;
}
@end
void SWELL_CFStringToCString(const void *str, char *buf, int buflen)
{
NSString *s = (NSString *)str;
if (buflen>0) *buf=0;
if (buflen <= 1 || !s || [s getCString:buf maxLength:buflen encoding:NSUTF8StringEncoding]) return; // should always work, I'd hope (ambiguous documentation ugh)
NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
if (!data)
{
[s getCString:buf maxLength:buflen encoding:NSASCIIStringEncoding];
return;
}
int len = (int)[data length];
if (len > buflen-1) len=buflen-1;
[data getBytes:buf length:len];
buf[len]=0;
}
void *SWELL_CStringToCFString(const char *str)
{
if (!str) str="";
void *ret;
ret=(void *)CFStringCreateWithCString(NULL,str,kCFStringEncodingUTF8);
if (ret) return ret;
ret=(void*)CFStringCreateWithCString(NULL,str,kCFStringEncodingASCII);
return ret;
}
void SWELL_MakeProcessFront(HANDLE h)
{
SWELL_InternalObjectHeader_NSTask *buf = (SWELL_InternalObjectHeader_NSTask*)h;
if (buf && buf->hdr.type == INTERNAL_OBJECT_NSTASK && buf->task)
{
ProcessSerialNumber psn;
int pid=[(id)buf->task processIdentifier];
// try for 1sec to get the PSN, if it fails
int n = 20;
while (GetProcessForPID(pid,&psn) != noErr && n-- > 0)
{
Sleep(50);
}
if (n>0) SetFrontProcess(&psn);
}
}
void SWELL_ReleaseNSTask(void *p)
{
NSTask *a =(NSTask*)p;
if (a)
{
if (![a isRunning]) [a waitUntilExit]; // workaround for the system keeping a reference held on macOS 12+ at least
[a release];
}
}
DWORD SWELL_WaitForNSTask(void *p, DWORD msTO)
{
NSTask *a =(NSTask*)p;
const DWORD t = GetTickCount();
do
{
if (![a isRunning]) return WAIT_OBJECT_0;
if (msTO) Sleep(1);
}
while (msTO && (GetTickCount()-t) < msTO);
return [a isRunning] ? WAIT_TIMEOUT : WAIT_OBJECT_0;
}
HANDLE SWELL_CreateProcessIO(const char *exe, int nparams, const char **params, bool redirectIO)
{
NSString *ex = (NSString *)SWELL_CStringToCFString(exe);
NSMutableArray *ar = [[NSMutableArray alloc] initWithCapacity:nparams];
int x;
for (x=0;x <nparams;x++)
{
NSString *s = (NSString *)SWELL_CStringToCFString(params[x]?params[x]:"");
[ar addObject:s];
[s release];
}
NSTask *tsk = NULL;
@try {
tsk = [[NSTask alloc] init];
[tsk setLaunchPath:ex];
[tsk setArguments:ar];
if (redirectIO)
{
[tsk setStandardInput:[NSPipe pipe]];
[tsk setStandardOutput:[NSPipe pipe]];
[tsk setStandardError:[NSPipe pipe]];
}
[tsk launch];
}
@catch (NSException *exception) {
[tsk release];
tsk=0;
}
@catch (id ex) {
}
[ex release];
[ar release];
if (!tsk) return NULL;
SWELL_InternalObjectHeader_NSTask *buf = (SWELL_InternalObjectHeader_NSTask*)malloc(sizeof(SWELL_InternalObjectHeader_NSTask));
buf->hdr.type = INTERNAL_OBJECT_NSTASK;
buf->hdr.count=1;
buf->task = tsk;
return buf;
}
HANDLE SWELL_CreateProcess(const char *exe, int nparams, const char **params)
{
return SWELL_CreateProcessIO(exe,nparams,params,false);
}
int SWELL_GetProcessExitCode(HANDLE hand)
{
int rv=0;
SWELL_InternalObjectHeader_NSTask *hdr=(SWELL_InternalObjectHeader_NSTask*)hand;
if (!hdr || hdr->hdr.type != INTERNAL_OBJECT_NSTASK || !hdr->task) return -1;
@try {
if ([(NSTask *)hdr->task isRunning]) rv=-3;
else rv = [(NSTask *)hdr->task terminationStatus];
}
@catch (id ex) {
rv=-2;
}
return rv;
}
int SWELL_TerminateProcess(HANDLE hand)
{
int rv=0;
SWELL_InternalObjectHeader_NSTask *hdr=(SWELL_InternalObjectHeader_NSTask*)hand;
if (!hdr || hdr->hdr.type != INTERNAL_OBJECT_NSTASK || !hdr->task) return -1;
@try
{
[(NSTask *)hdr->task terminate];
}
@catch (id ex) {
rv=-2;
}
return rv;
}
int SWELL_ReadWriteProcessIO(HANDLE hand, int w/*stdin,stdout,stderr*/, char *buf, int bufsz)
{
SWELL_InternalObjectHeader_NSTask *hdr=(SWELL_InternalObjectHeader_NSTask*)hand;
if (!hdr || hdr->hdr.type != INTERNAL_OBJECT_NSTASK || !hdr->task) return 0;
NSTask *tsk = (NSTask*)hdr->task;
NSPipe *pipe = NULL;
bool async_mode = false;
if (w & (1<<24))
{
async_mode = true;
w &= ~ (1<<24);
}
switch (w)
{
case 0: pipe = [tsk standardInput]; break;
case 1: pipe = [tsk standardOutput]; break;
case 2: pipe = [tsk standardError]; break;
}
if (!pipe || ![pipe isKindOfClass:[NSPipe class]]) return 0;
NSFileHandle *fh = w!=0 ? [pipe fileHandleForReading] : [pipe fileHandleForWriting];
if (!fh) return 0;
if (w==0)
{
if (bufsz>0)
{
NSData *d = [NSData dataWithBytes:buf length:bufsz];
@try
{
if (d) [fh writeData:d];
else bufsz=0;
}
@catch (id ex) { bufsz=0; }
return bufsz;
}
}
else
{
if (async_mode)
{
int handle = [fh fileDescriptor];
if (handle >= 0)
{
struct pollfd pl = { handle, POLLIN };
if (poll(&pl,1,0)<1) return 0;
return (int)read(handle,buf,bufsz);
}
}
NSData *d = NULL;
@try
{
d = [fh readDataOfLength:(bufsz < 1 ? 32768 : bufsz)];
}
@catch (id ex) { }
if (!d || bufsz < 1) return d ? (int)[d length] : 0;
int l = (int)[d length];
if (l > bufsz) l = bufsz;
[d getBytes:buf length:l];
return l;
}
return 0;
}
@implementation SWELL_ThreadTmp
-(void)bla:(id)obj
{
if (a)
{
DWORD (*func)(void *);
*(void **)(&func) = a;
func(b);
}
[NSThread exit];
}
@end
void SWELL_EnsureMultithreadedCocoa()
{
static int a;
if (!a)
{
a++;
if (![NSThread isMultiThreaded]) // force cocoa into multithreaded mode
{
SWELL_ThreadTmp *t=[[SWELL_ThreadTmp alloc] init];
t->a=0;
t->b=0;
[NSThread detachNewThreadSelector:@selector(bla:) toTarget:t withObject:t];
/// [t release];
}
}
}
void CreateThreadNS(void *TA, DWORD stackSize, DWORD (*ThreadProc)(LPVOID), LPVOID parm, DWORD cf, DWORD *tidOut)
{
SWELL_ThreadTmp *t=[[SWELL_ThreadTmp alloc] init];
t->a=(void*)ThreadProc;
t->b=parm;
return [NSThread detachNewThreadSelector:@selector(bla:) toTarget:t withObject:t];
}
// used by swell.cpp (lazy these should go elsewhere)
void *SWELL_InitAutoRelease()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
return (void *)pool;
}
void SWELL_QuitAutoRelease(void *p)
{
if (p)
[(NSAutoreleasePool*)p release];
}
void SWELL_RunEvents()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int x=100;
while (x-- > 0)
{
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.001] inMode:NSDefaultRunLoopMode dequeue:YES];
if (!event) break;
[NSApp sendEvent:event];
}
[pool release];
}
// timer stuff
typedef struct TimerInfoRec
{
UINT_PTR timerid;
HWND hwnd;
NSTimer *timer;
struct TimerInfoRec *_next;
} TimerInfoRec;
static TimerInfoRec *m_timer_list;
static WDL_Mutex m_timermutex;
#ifndef SWELL_NO_POSTMESSAGE
static pthread_t m_pmq_mainthread;
static void SWELL_pmq_settimer(HWND h, UINT_PTR timerid, UINT rate, TIMERPROC tProc);
#endif
UINT_PTR SetTimer(HWND hwnd, UINT_PTR timerid, UINT rate, TIMERPROC tProc)
{
if (!hwnd && !tProc) return 0; // must have either callback or hwnd
if (hwnd && !timerid) return 0;
#ifndef SWELL_NO_POSTMESSAGE
if (timerid != ~(UINT_PTR)0 && m_pmq_mainthread && pthread_self()!=m_pmq_mainthread)
{
SWELL_pmq_settimer(hwnd,timerid,(rate==(UINT)-1)?((UINT)-2):rate,tProc);
return timerid;
}
#endif
if (hwnd && ![(id)hwnd respondsToSelector:@selector(SWELL_Timer:)])
{
if (![(id)hwnd isKindOfClass:[NSWindow class]]) return 0;
hwnd=(HWND)[(id)hwnd contentView];
if (![(id)hwnd respondsToSelector:@selector(SWELL_Timer:)]) return 0;
}
WDL_MutexLock lock(&m_timermutex);
TimerInfoRec *rec=NULL;
if (hwnd||timerid)
{
rec = m_timer_list;
while (rec)
{
if (rec->timerid == timerid && rec->hwnd == hwnd) // works for both kinds
break;
rec=rec->_next;
}
}
bool recAdd=false;
if (!rec)
{
rec=(TimerInfoRec*)malloc(sizeof(TimerInfoRec));
recAdd=true;
}
else
{
[rec->timer invalidate];
rec->timer=0;
}
rec->timerid=timerid;
rec->hwnd=hwnd;
if (!hwnd || tProc)
{
// set timer to this unique ptr
if (!hwnd) timerid = rec->timerid = (UINT_PTR)rec;
SWELL_TimerFuncTarget *t = [[SWELL_TimerFuncTarget alloc] initWithId:timerid hwnd:hwnd callback:tProc];
rec->timer = [NSTimer scheduledTimerWithTimeInterval:(wdl_max(rate,1)*0.001) target:t selector:@selector(SWELL_Timer:)
userInfo:t repeats:YES];
[t release];
}
else
{
SWELL_DataHold *t=[[SWELL_DataHold alloc] initWithVal:(void *)timerid];
rec->timer = [NSTimer scheduledTimerWithTimeInterval:(wdl_max(rate,1)*0.001) target:(id)hwnd selector:@selector(SWELL_Timer:)
userInfo:t repeats:YES];
[t release];
}
[[NSRunLoop currentRunLoop] addTimer:rec->timer forMode:(NSString*)kCFRunLoopCommonModes];
if (recAdd)
{
rec->_next=m_timer_list;
m_timer_list=rec;
}
return timerid;
}
void SWELL_RunRunLoop(int ms)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:ms*0.001]];
}
void SWELL_RunRunLoopEx(int ms, HWND hwndOnlyTimer)
{
HWND h=g_swell_only_timerhwnd;
g_swell_only_timerhwnd = hwndOnlyTimer;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:ms*0.001]];
if (g_swell_only_timerhwnd == hwndOnlyTimer) g_swell_only_timerhwnd = h;
}
BOOL KillTimer(HWND hwnd, UINT_PTR timerid)
{
if (!hwnd && !timerid) return FALSE;
WDL_MutexLock lock(&m_timermutex);
#ifndef SWELL_NO_POSTMESSAGE
if (timerid != ~(UINT_PTR)0 && m_pmq_mainthread && pthread_self()!=m_pmq_mainthread)
{
SWELL_pmq_settimer(hwnd,timerid,~(UINT)0,NULL);
return TRUE;
}
#endif
BOOL rv=FALSE;
// don't allow removing all global timers
if (timerid!=~(UINT_PTR)0 || hwnd)
{
TimerInfoRec *rec = m_timer_list, *lrec=NULL;
while (rec)
{
if (rec->hwnd == hwnd && (timerid==~(UINT_PTR)0 || rec->timerid == timerid))
{
TimerInfoRec *nrec = rec->_next;
// remove self from list
if (lrec) lrec->_next = nrec;
else m_timer_list = nrec;
[rec->timer invalidate];
free(rec);
rv=TRUE;
if (timerid!=~(UINT_PTR)0) break;
rec=nrec;
}
else
{
lrec=rec;
rec=rec->_next;
}
}
}
return rv;
}
#ifndef SWELL_NO_POSTMESSAGE
///////// PostMessage emulation
// implementation of postmessage stuff
typedef struct PMQ_rec
{
HWND hwnd;
UINT msg;
WPARAM wParam;
LPARAM lParam;
struct PMQ_rec *next;
bool is_special_timer; // if set, then msg=interval(-1 for kill),wParam=timer id, lParam = timerproc
} PMQ_rec;
static WDL_Mutex *m_pmq_mutex;
static PMQ_rec *m_pmq, *m_pmq_empty, *m_pmq_tail;
static int m_pmq_size;
static id m_pmq_timer;
#define MAX_POSTMESSAGE_SIZE 1024
void SWELL_Internal_PostMessage_Init()
{
if (m_pmq_mutex) return;
id del = [NSApp delegate];
if (!del || ![del respondsToSelector:@selector(swellPostMessageTick:)]) return;
m_pmq_mainthread=pthread_self();
m_pmq_mutex = new WDL_Mutex;
m_pmq_timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:(id)del selector:@selector(swellPostMessageTick:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:m_pmq_timer forMode:(NSString*)kCFRunLoopCommonModes];
// [ release];
// set a timer to the delegate
}
void SWELL_MessageQueue_Flush()
{
if (!m_pmq_mutex) return;
m_pmq_mutex->Enter();
int max_amt = m_pmq_size;
PMQ_rec *p=m_pmq;
if (p)
{
m_pmq = p->next;
if (m_pmq_tail == p) m_pmq_tail=NULL;
m_pmq_size--;
}
m_pmq_mutex->Leave();
// process out queue
while (p)
{
if (p->is_special_timer)
{
if (p->msg == ~(UINT)0) KillTimer(p->hwnd,p->wParam);
else SetTimer(p->hwnd,p->wParam,p->msg,(TIMERPROC)p->lParam);
}
else
{
if ([(id)p->hwnd respondsToSelector:@selector(swellCanPostMessage)] && [(id)p->hwnd swellCanPostMessage])
SendMessage(p->hwnd,p->msg,p->wParam,p->lParam);
}
m_pmq_mutex->Enter();
// move this message to empty list
p->next=m_pmq_empty;
m_pmq_empty = p;
// get next queued message (if within limits)
p = (--max_amt > 0) ? m_pmq : NULL;
if (p)
{
m_pmq = p->next;
if (m_pmq_tail == p) m_pmq_tail=NULL;
m_pmq_size--;
}
m_pmq_mutex->Leave();
}
}
void SWELL_Internal_PMQ_ClearAllMessages(HWND hwnd)
{
if (!m_pmq_mutex) return;
m_pmq_mutex->Enter();
PMQ_rec *p=m_pmq;
PMQ_rec *lastrec=NULL;
while (p)
{
if (hwnd && p->hwnd != hwnd) { lastrec=p; p=p->next; }
else
{
PMQ_rec *next=p->next;
p->next=m_pmq_empty; // add p to empty list
m_pmq_empty=p;
m_pmq_size--;
if (p==m_pmq_tail) m_pmq_tail=lastrec; // update tail
if (lastrec) p = lastrec->next = next;
else p = m_pmq = next;
}
}
m_pmq_mutex->Leave();
}
static void SWELL_pmq_settimer(HWND h, UINT_PTR timerid, UINT rate, TIMERPROC tProc)
{
if (!h||!m_pmq_mutex) return;
WDL_MutexLock lock(m_pmq_mutex);
PMQ_rec *rec=m_pmq;
while (rec)
{
if (rec->is_special_timer && rec->hwnd == h && rec->wParam == timerid)
{
rec->msg = rate; // adjust to new rate
rec->lParam = (LPARAM)tProc;
return;
}
rec=rec->next;
}
rec=m_pmq_empty;
if (rec) m_pmq_empty=rec->next;
else rec=(PMQ_rec*)malloc(sizeof(PMQ_rec));
rec->next=0;
rec->hwnd=h;
rec->msg=rate;
rec->wParam=timerid;
rec->lParam=(LPARAM)tProc;
rec->is_special_timer=true;
if (m_pmq_tail) m_pmq_tail->next=rec;
else
{
PMQ_rec *p=m_pmq;
while (p && p->next) p=p->next; // shouldnt happen unless m_pmq is NULL As well but why not for safety
if (p) p->next=rec;
else m_pmq=rec;
}
m_pmq_tail=rec;
m_pmq_size++;
}
BOOL PostMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (WDL_NORMALLY(m_pmq_mutex != NULL))
{
return SWELL_Internal_PostMessage(hwnd,message,wParam,lParam);
}
// legacy passthrough to delegate if caller is using its own swell impl, not threadsafe
id del=[NSApp delegate];
if (del && [del respondsToSelector:@selector(swellPostMessage:msg:wp:lp:)])
return !![(SWELL_DelegateExtensions*)del swellPostMessage:hwnd msg:message wp:wParam lp:lParam];
return FALSE;
}
void SWELL_MessageQueue_Clear(HWND h)
{
if (WDL_NORMALLY(m_pmq_mutex != NULL))
{
SWELL_Internal_PMQ_ClearAllMessages(h);
}
else
{
id del=[NSApp delegate];
if (del && [del respondsToSelector:@selector(swellPostMessageClearQ:)])
[(SWELL_DelegateExtensions*)del swellPostMessageClearQ:h];
}
}
BOOL SWELL_Internal_PostMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (!hwnd||!m_pmq_mutex) return FALSE;
BOOL ret=FALSE;
m_pmq_mutex->Enter();
if (m_pmq_empty||m_pmq_size<MAX_POSTMESSAGE_SIZE)
{
PMQ_rec *rec=m_pmq_empty;
if (rec) m_pmq_empty=rec->next;
else rec=(PMQ_rec*)malloc(sizeof(PMQ_rec));
rec->next=0;
rec->hwnd=hwnd;
rec->msg=msg;
rec->wParam=wParam;
rec->lParam=lParam;
rec->is_special_timer=false;
if (m_pmq_tail) m_pmq_tail->next=rec;
else
{
PMQ_rec *p=m_pmq;
while (p && p->next) p=p->next; // shouldnt happen unless m_pmq is NULL As well but why not for safety
if (p) p->next=rec;
else m_pmq=rec;
}
m_pmq_tail=rec;
m_pmq_size++;
ret=TRUE;
}
m_pmq_mutex->Leave();
return ret;
}
#endif
static bool s_rightclickemulate=true;
bool IsRightClickEmulateEnabled()
{
return s_rightclickemulate;
}
void SWELL_EnableRightClickEmulate(BOOL enable)
{
s_rightclickemulate=enable;
}
int g_swell_terminating;
void SWELL_PostQuitMessage(void *sender)
{
g_swell_terminating=true;
[NSApp terminate:(id)sender];
}
#ifndef MAC_OS_X_VERSION_10_9
typedef uint64_t NSActivityOptions;
enum
{
NSActivityIdleDisplaySleepDisabled = (1ULL << 40),
NSActivityIdleSystemSleepDisabled = (1ULL << 20),
NSActivitySuddenTerminationDisabled = (1ULL << 14),
NSActivityAutomaticTerminationDisabled = (1ULL << 15),
NSActivityUserInitiated = (0x00FFFFFFULL | NSActivityIdleSystemSleepDisabled),
NSActivityUserInitiatedAllowingIdleSystemSleep = (NSActivityUserInitiated & ~NSActivityIdleSystemSleepDisabled),
NSActivityBackground = 0x000000FFULL,
NSActivityLatencyCritical = 0xFF00000000ULL,
};
@interface NSProcessInfo (reaperhostadditions)
- (id<NSObject>)beginActivityWithOptions:(NSActivityOptions)options reason:(NSString *)reason;
- (void)endActivity:(id<NSObject>)activity;
@end
#endif
void SWELL_DisableAppNap(int disable)
{
if (!g_swell_terminating && floor(NSFoundationVersionNumber) > 945.00) // 10.9+
{
static int cnt;
static id obj;
cnt += disable;
@try
{
if (cnt > 0)
{
if (!obj)
{
const NSActivityOptions v = NSActivityLatencyCritical | NSActivityIdleSystemSleepDisabled;
// beginActivityWithOptions returns an autoreleased object
obj = [[NSProcessInfo processInfo] beginActivityWithOptions:v reason:@"SWELL_DisableAppNap"];
if (obj) [obj retain];
}
}
else
{
id a = obj;
if (a)
{
// in case we crash somehow, dont' want obj sticking around pointing to a stale object
obj = NULL;
[[NSProcessInfo processInfo] endActivity:a];
[a release]; // apparently releasing this is enough, without the endActivity call, but the docs are quite vague
}
}
}
@catch (NSException *exception) {
}
@catch (id ex) {
}
}
}
BOOL EnumDisplayMonitors(HDC hdc, const LPRECT r, MONITORENUMPROC proc,LPARAM lParam)
{
// ignores hdc
NSArray *screens = [NSScreen screens];
const unsigned int ns = (unsigned int) [screens count];
for (unsigned int x = 0; x < ns; x ++)
{
NSScreen *mon = [screens objectAtIndex:x];
if (mon)
{
NSRect tr=[mon frame];
RECT screen_rect,tmp;
NSRECT_TO_RECT(&tmp,tr);
if (r)
{
if (!IntersectRect(&screen_rect,r,&tmp))
continue;
}
else
{
screen_rect = tmp;
}
if (!proc((HMONITOR)mon,hdc,&screen_rect,lParam)) break;
}
}
return TRUE;
}
BOOL GetMonitorInfo(HMONITOR hmon, void *inf)
{
if (!hmon) return FALSE;
MONITORINFOEX *a = (MONITORINFOEX*)inf;
if (a->cbSize < sizeof(MONITORINFO)) return FALSE;
NSScreen *mon = (NSScreen *)hmon;
NSRect tr=[mon frame];
NSRECT_TO_RECT(&a->rcMonitor,tr);
tr = [mon visibleFrame];
NSRECT_TO_RECT(&a->rcWork,tr);
a->dwFlags = 0;
if (a->cbSize > sizeof(MONITORINFO))
{
const int maxlen = (int) (a->cbSize - sizeof(MONITORINFO));
const int displayID = [[[mon deviceDescription] valueForKey:@"NSScreenNumber"] intValue];
snprintf(a->szDevice,maxlen,"DisplayID %d",displayID);
static bool init;
static CFDictionaryRef (*_IODisplayCreateInfoDictionary)(io_service_t framebuffer, IOOptionBits options);
if (!init)
{
init = true;
void *lib = dlopen("/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit",RTLD_LAZY);
if (lib)
*(void **)&_IODisplayCreateInfoDictionary = dlsym(lib,"IODisplayCreateInfoDictionary");
}
if (_IODisplayCreateInfoDictionary)
{
NSDictionary *deviceInfo = (NSDictionary *)_IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
NSDictionary *names = [deviceInfo objectForKey:@"DisplayProductName"];
if ([names count] > 0)
{
NSString *s = [names objectForKey:[[names allKeys] objectAtIndex:0]];
if (s) SWELL_CFStringToCString(s,a->szDevice,maxlen);
}
[deviceInfo release];
}
}
return TRUE;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,767 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides basic APIs for browsing for files, directories, and messageboxes.
These APIs don't all match the Windows equivelents, but are close enough to make it not too much trouble.
*/
#ifndef SWELL_PROVIDED_BY_APP
#include "swell.h"
#include "swell-dlggen.h"
#include "../wdlcstring.h"
#import <Cocoa/Cocoa.h>
#include "swell-internal.h"
struct swell_autoarp {
swell_autoarp() { pool = [[NSAutoreleasePool alloc] init]; }
~swell_autoarp() { [pool release]; }
NSAutoreleasePool *pool;
};
static NSMutableArray *extensionsFromList(const char *extlist, const char *def_ext=NULL)
{
NSMutableArray *fileTypes = [[NSMutableArray alloc] initWithCapacity:30];
while (*extlist)
{
extlist += strlen(extlist)+1;
if (!*extlist) break;
while (*extlist)
{
while (*extlist && *extlist != '.') extlist++;
if (!*extlist) break;
extlist++;
char tmp[32];
lstrcpyn_safe(tmp,extlist,sizeof(tmp));
if (strstr(tmp,";")) strstr(tmp,";")[0]=0;
if (tmp[0] && tmp[0]!='*')
{
NSString *s=(NSString *)SWELL_CStringToCFString(tmp);
const size_t tmp_len = strlen(tmp);
if (def_ext && *def_ext &&
!strnicmp(def_ext,tmp,tmp_len) &&
(!def_ext[tmp_len] || def_ext[tmp_len] == ';'))
[fileTypes insertObject:s atIndex:0];
else
[fileTypes addObject:s];
[s release];
}
while (*extlist && *extlist != ';') extlist++;
if (*extlist == ';') extlist++;
}
extlist++;
}
return fileTypes;
}
static const char *BFSF_Templ_dlgid;
static DLGPROC BFSF_Templ_dlgproc;
static struct SWELL_DialogResourceIndex *BFSF_Templ_reshead;
void BrowseFile_SetTemplate(const char *dlgid, DLGPROC dlgProc, struct SWELL_DialogResourceIndex *reshead)
{
BFSF_Templ_reshead=reshead;
BFSF_Templ_dlgid=dlgid;
BFSF_Templ_dlgproc=dlgProc;
}
static const char *s_browse_extsel;
static LRESULT fileTypeChooseProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
const int wndh = 22, lblw = 80, combow = 250, def_wid = lblw + 4 + combow + 4;
switch (uMsg)
{
case WM_CREATE:
SetOpaque(hwnd,FALSE);
SWELL_MakeSetCurParms(1,1,0,0,hwnd,true,false);
SWELL_MakeLabel(1,"File type:",1001,0,2,lblw,wndh,0);
SWELL_MakeCombo(1000, lblw + 4,0, combow, wndh,3/*CBS_DROPDOWNLIST*/);
SWELL_MakeSetCurParms(1,1,0,0,NULL,false,false);
SetWindowPos(hwnd,NULL,0,0,def_wid,wndh,SWP_NOMOVE|SWP_NOZORDER);
{
const char *extlist = ((const char **)lParam)[0];
SetWindowLongPtr(hwnd,GWLP_USERDATA,(LPARAM)extlist);
const char *initial_file = ((const char **)lParam)[1];
if (initial_file) initial_file=WDL_get_fileext(initial_file);
const size_t initial_file_len = initial_file && *initial_file ? strlen(++initial_file) : 0;
int def_sel = -1;
HWND combo = GetDlgItem(hwnd,1000);
while (*extlist)
{
const char *next = extlist + strlen(extlist)+1;
if (!*next) break;
if (strcmp(next,"*.*"))
{
int a = (int)SendMessage(combo,CB_ADDSTRING,0,(LPARAM)extlist);
// userdata for each item is pointer to un-terminated extension.
const char *p = next;
while (*p && *p != '.') p++;
if (*p) p++;
const char *bestp = p;
// scan extension list for matching initial file, use that (and set default)
if (def_sel < 0 && initial_file) while (*p)
{
if (!strnicmp(p,initial_file,initial_file_len) && (p[initial_file_len] == ';' || !p[initial_file_len]))
{
s_browse_extsel = p;
bestp = p;
def_sel = a;
break;
}
else
{
while (*p && *p != '.') p++;
if (*p) p++;
}
}
SendMessage(combo,CB_SETITEMDATA,a,(LPARAM)bestp);
}
extlist = next + strlen(next)+1;
if (!*extlist) break;
}
SendMessage(combo,CB_SETCURSEL,def_sel>=0?def_sel:0,0);
}
return 0;
case WM_SIZE:
{
RECT r;
GetClientRect(hwnd,&r);
const int xpos = r.right / 2 - def_wid/2;
SetWindowPos(GetDlgItem(hwnd,1001),NULL, xpos,2,0,0,SWP_NOZORDER|SWP_NOSIZE);
SetWindowPos(GetDlgItem(hwnd,1000),NULL, xpos + lblw + 4,0,0,0,SWP_NOZORDER|SWP_NOSIZE);
}
return 0;
case WM_COMMAND:
if (LOWORD(wParam) == 1000 && HIWORD(wParam) == CBN_SELCHANGE)
{
int a = (int)SendDlgItemMessage(hwnd,1000,CB_GETCURSEL,0,0);
if (a>=0)
{
const char *extlist = (const char *)GetWindowLongPtr(hwnd,GWLP_USERDATA);
if (extlist)
{
NSArray *fileTypes = extensionsFromList(extlist,
s_browse_extsel = (const char *)SendDlgItemMessage(hwnd,1000,CB_GETITEMDATA,a,0)
);
if ([fileTypes count]>0)
{
NSSavePanel *par = (NSSavePanel*)GetWindowLongPtr(hwnd,0);
if (par && [par isKindOfClass:[NSSavePanel class]]) [(NSSavePanel *)par setAllowedFileTypes:fileTypes];
}
[fileTypes release];
}
}
}
return 0;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
static void restoreMenuForFocus()
{
HWND h = GetFocus();
HMENU menu = h ? GetMenu(h) : NULL;
if (!menu)
menu = SWELL_GetDefaultWindowMenu();
if (menu)
SWELL_SetCurrentMenu(menu);
}
// return true
bool BrowseForSaveFile(const char *text, const char *initialdir, const char *initialfile, const char *extlist,
char *fn, int fnsize)
{
swell_autoarp auto_arp;
NSSavePanel *panel = [NSSavePanel savePanel];
NSMutableArray *fileTypes = extensionsFromList(extlist);
NSString *title=(NSString *)SWELL_CStringToCFString(text);
NSString *ifn=NULL, *idir = NULL;
[panel setTitle:title];
[panel setAccessoryView:nil];
HWND av_parent = (HWND)panel;
s_browse_extsel = NULL;
if ([fileTypes count]>1)
{
const char *ar[2]={extlist,initialfile};
av_parent = SWELL_CreateDialog(NULL,0,NULL,fileTypeChooseProc,(LPARAM)ar);
if (!av_parent) av_parent = (HWND)panel;
else SetWindowLongPtr(av_parent, 0, (LPARAM)panel);
}
HWND oh=NULL;
if (BFSF_Templ_dlgproc && BFSF_Templ_dlgid) // create a child dialog and set it to the panel
{
oh=SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, av_parent, BFSF_Templ_dlgproc, 0);
BFSF_Templ_dlgproc=0;
BFSF_Templ_dlgid=0;
}
if (av_parent != (HWND)panel)
{
if (oh)
{
RECT r1,r2;
GetClientRect(oh,&r1);
GetClientRect(av_parent,&r2);
SetWindowPos(oh,NULL,0,r2.bottom,0,0,SWP_NOZORDER|SWP_NOSIZE);
if (r2.right < r1.right) r2.right=r1.right;
SetWindowPos(av_parent,NULL,0,0,r2.right,r2.bottom+r1.bottom,SWP_NOZORDER|SWP_NOMOVE);
ShowWindow(oh,SW_SHOWNA);
}
oh = av_parent;
NSWindow *oldw = [(NSView *)av_parent window];
[panel setAccessoryView:(NSView *)av_parent]; // we resized our accessory view
SendMessage(av_parent,WM_COMMAND,(CBN_SELCHANGE<<16) | 1000,(LPARAM)GetDlgItem(av_parent,1000));
[(NSView *)av_parent setHidden:NO];
[oldw release];
}
else if ([fileTypes count]>0)
{
[panel setAllowedFileTypes:fileTypes];
}
if (initialfile && *initialfile && *initialfile != '.')
{
char s[2048];
lstrcpyn_safe(s,initialfile,sizeof(s));
if (ext_valid_for_extlist(WDL_get_fileext(initialfile),extlist)>=0)
WDL_remove_fileext(s);
char *p=s;
while (*p) p++;
while (p >= s && *p != '/') p--;
if (p>=s)
{
*p=0;
ifn=(NSString *)SWELL_CStringToCFString(p+1);
idir=(NSString *)SWELL_CStringToCFString(s[0]?s:"/");
}
else
ifn=(NSString *)SWELL_CStringToCFString(s);
}
if (!idir && initialdir && *initialdir)
{
idir=(NSString *)SWELL_CStringToCFString(initialdir);
}
HMENU hm=SWELL_GetDefaultModalWindowMenu();
if (hm)
{
hm=SWELL_DuplicateMenu(hm);
SWELL_SetCurrentMenu(hm);
}
NSInteger result = [panel runModalForDirectory:idir file:ifn];
restoreMenuForFocus();
if (hm) DestroyMenu(hm);
if (oh) SendMessage(oh,WM_DESTROY,0,0);
[panel setAccessoryView:nil];
bool rv = false;
NSString *str;
if (result == NSOKButton && fn && fnsize > 0 && (str = [panel filename]))
{
SWELL_CFStringToCString(str,fn,fnsize);
if (fn[0])
{
char tmp[256];
const NSUInteger nft = [fileTypes count];
NSUInteger x = nft;
const char *ext = WDL_get_fileext(fn);
if (*ext)
{
// see if extension is in list
ext++;
for (x = 0; x < nft; x ++)
{
NSString *s = [fileTypes objectAtIndex:x];
if (s)
{
SWELL_CFStringToCString(s,tmp,sizeof(tmp));
if (!stricmp(tmp,ext)) break;
}
}
}
if (x == nft)
{
// this might no longer be necessary -- it was at one point when [accessoryview window] was not a NSSavePanel,
// but we fixed that, so the extension should always be applied (probably)
// not in list: apply last-selected extension, then default extension, if specified, or first extension from list
if (s_browse_extsel && *s_browse_extsel)
{
lstrcatn(fn,".",fnsize);
lstrcatn(fn,s_browse_extsel,fnsize);
}
else if (initialfile && *initialfile == '.')
{
lstrcatn(fn,initialfile,fnsize);
}
else if (nft > 0)
{
NSString *s = [fileTypes objectAtIndex:0];
if (s)
{
tmp[0] = '.';
SWELL_CFStringToCString(s,tmp+1,sizeof(tmp)-1);
lstrcatn(fn,tmp,fnsize);
}
}
}
rv = true;
}
}
[title release];
[fileTypes release];
[idir release];
[ifn release];
return rv;
}
bool BrowseForDirectory(const char *text, const char *initialdir, char *fn, int fnsize)
{
swell_autoarp auto_arp;
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSString *title=(NSString *)SWELL_CStringToCFString(text);
NSString *idir=NULL;
[panel setTitle:title];
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseFiles:NO];
[panel setCanCreateDirectories:YES];
[panel setCanChooseDirectories:YES];
[panel setResolvesAliases:YES];
HWND oh=NULL;
if (BFSF_Templ_dlgproc && BFSF_Templ_dlgid) // create a child dialog and set it to the panel
{
oh=SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, (HWND)panel, BFSF_Templ_dlgproc, 0);
BFSF_Templ_dlgproc=0;
BFSF_Templ_dlgid=0;
}
if (initialdir && *initialdir)
{
idir=(NSString *)SWELL_CStringToCFString(initialdir);
}
HMENU hm=SWELL_GetDefaultModalWindowMenu();
if (hm)
{
hm=SWELL_DuplicateMenu(hm);
SWELL_SetCurrentMenu(hm);
}
NSInteger result = [panel runModalForDirectory:idir file:nil types:nil];
restoreMenuForFocus();
if (hm) DestroyMenu(hm);
if (oh) SendMessage(oh,WM_DESTROY,0,0);
[panel setAccessoryView:nil];
[idir release];
[title release];
if (result != NSOKButton) return 0;
NSArray *filesToOpen = [panel filenames];
NSInteger count = [filesToOpen count];
if (!count) return 0;
NSString *aFile = [filesToOpen objectAtIndex:0];
if (!aFile) return 0;
if (fn && fnsize>0)
{
SWELL_CFStringToCString(aFile,fn,fnsize);
fn[fnsize-1]=0;
}
return 1;
}
char *BrowseForFiles(const char *text, const char *initialdir,
const char *initialfile, bool allowmul, const char *extlist)
{
swell_autoarp auto_arp;
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSString *title=(NSString *)SWELL_CStringToCFString(text);
NSString *ifn=NULL, *idir=NULL;
NSMutableArray *fileTypes = extensionsFromList(extlist);
HWND oh=NULL;
if (BFSF_Templ_dlgproc && BFSF_Templ_dlgid) // create a child dialog and set it to the panel
{
oh=SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, (HWND)panel, BFSF_Templ_dlgproc, 0);
BFSF_Templ_dlgproc=0;
BFSF_Templ_dlgid=0;
}
[panel setTitle:title];
[panel setAllowsMultipleSelection:(allowmul?YES:NO)];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setResolvesAliases:YES];
if (initialfile && *initialfile)
{
char s[2048];
lstrcpyn_safe(s,initialfile,sizeof(s));
char *p=s;
while (*p) p++;
while (p >= s && *p != '/') p--;
if (p>=s)
{
*p=0;
ifn=(NSString *)SWELL_CStringToCFString(p+1);
idir=(NSString *)SWELL_CStringToCFString(s[0]?s:"/");
}
else
ifn=(NSString *)SWELL_CStringToCFString(s);
}
if (!idir && initialdir && *initialdir)
{
idir=(NSString *)SWELL_CStringToCFString(initialdir);
}
HMENU hm=SWELL_GetDefaultModalWindowMenu();
if (hm)
{
hm=SWELL_DuplicateMenu(hm);
SWELL_SetCurrentMenu(hm);
}
NSInteger result = [panel runModalForDirectory:idir file:ifn types:([fileTypes count]>0 ? fileTypes : nil)];
restoreMenuForFocus();
if (hm) DestroyMenu(hm);
if (oh) SendMessage(oh,WM_DESTROY,0,0);
[panel setAccessoryView:nil];
[ifn release];
[idir release];
[fileTypes release];
[title release];
if (result != NSOKButton) return 0;
NSArray *filesToOpen = [panel filenames];
const NSInteger count = [filesToOpen count];
if (!count) return 0;
char fn[2048];
if (count==1||!allowmul)
{
NSString *aFile = [filesToOpen objectAtIndex:0];
if (!aFile) return 0;
SWELL_CFStringToCString(aFile,fn,sizeof(fn));
fn[sizeof(fn)-1]=0;
char *ret=(char *)malloc(strlen(fn)+2);
memcpy(ret,fn,strlen(fn));
ret[strlen(fn)]=0;
ret[strlen(fn)+1]=0;
return ret;
}
size_t rsize=1;
char *ret=0;
for (NSInteger i=0; i<count; i++)
{
NSString *aFile = [filesToOpen objectAtIndex:i];
if (!aFile) continue;
SWELL_CFStringToCString(aFile,fn,sizeof(fn));
fn[sizeof(fn)-1]=0;
size_t tlen=strlen(fn)+1;
ret=(char *)realloc(ret,rsize+tlen+1);
if (!ret) return 0;
if (rsize==1) ret[0]=0;
strcpy(ret+rsize,fn);
rsize+=tlen;
ret[rsize]=0;
}
return ret;
}
static NSString *mbidtostr(int idx)
{
switch (idx)
{
case IDOK: return @"OK";
case IDCANCEL: return @"Cancel";
case IDYES: return @"Yes";
case IDNO: return @"No";
case IDRETRY: return @"Retry";
case IDABORT: return @"Abort";
case IDIGNORE: return @"Ignore";
default:
WDL_ASSERT(idx == 0);
return @"";
}
}
int MessageBox(HWND hwndParent, const char *text, const char *caption, int type)
{
swell_autoarp auto_arp;
NSString *title = (NSString *)SWELL_CStringToCFString(caption?caption:"");
NSString *text2 = (NSString *)SWELL_CStringToCFString(text?text:"");
int b1=IDOK, b2=0, b3=0;
switch (type & 0xf)
{
case MB_ABORTRETRYIGNORE:
b1 = IDABORT;
b2 = IDRETRY;
b3 = IDIGNORE;
break;
case MB_RETRYCANCEL:
b1 = IDRETRY;
// fallthrough
case MB_OKCANCEL:
b2 = IDCANCEL;
break;
case MB_YESNOCANCEL:
b3 = IDCANCEL;
// fallthrough
case MB_YESNO:
b1 = IDYES;
b2 = IDNO;
break;
}
if ((type & MB_DEFBUTTON3) && b3)
{
// rotate buttons right (making b3 the default)
const int tmp = b3;
b3 = b2;
b2 = b1;
b1 = tmp;
}
else if ((type & MB_DEFBUTTON2) && b2)
{
// rotate buttons left
const int tmp = b1;
b1 = b2;
b2 = b3 ? b3 : tmp;
if (b3) b3=tmp;
}
if (b2 && b3)
{
// NSRunAlertPanel ordering meh
const int tmp = b3;
b3 = b2;
b2 = tmp;
}
NSInteger ret = NSRunAlertPanel(title,@"%@",mbidtostr(b1),mbidtostr(b2),mbidtostr(b3),text2);
[text2 release];
[title release];
return ret > 0 ? b1 : ret < 0 ? b3 : b2;
}
static WDL_DLGRET color_okCancelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
SetWindowLongPtr(hwndDlg,0,0);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
SetWindowLongPtr(hwndDlg,0,1);
break;
case IDCANCEL:
SetWindowLongPtr(hwndDlg,0,2);
break;
}
break;
}
return 0;
}
static void okcancel_create(HWND hwnd, int f)
{
SWELL_MakeSetCurParms(1.7,1.7,0,0,hwnd,false,false);
SWELL_MakeButton(1,"OK",IDOK,48,2,44,14,0);
SWELL_MakeButton(1,"Cancel",IDCANCEL,2,2,44,14,0);
SWELL_MakeSetCurParms(1.7,1.7,0,0,NULL,false,false);
}
static HWND makeOKcancel(HWND par)
{
const char *dlgid = "";
SWELL_DialogResourceIndex tmph = {
dlgid, "",
SWELL_DLG_WS_FLIPPED|SWELL_DLG_WS_NOAUTOSIZE|SWELL_DLG_WS_CHILD,
okcancel_create,
(int)(98*1.7),(int)(18*1.7),
NULL
};
return SWELL_CreateDialog(&tmph,dlgid,par,color_okCancelProc,0);
}
static bool ColorFromNSColor(NSColor *color, COLORREF *colout)
{
if (!color) return false;
CGFloat r,g,b;
NSColor *color2=[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
if (!color2) return false;
[color2 getRed:&r green:&g blue:&b alpha:NULL];
int rv=(int)(r*255.0 + 0.5);
int gv=(int)(g*255.0 + 0.5);
int bv=(int)(b*255.0 + 0.5);
if (rv<0)rv=0; else if (rv>255)rv=255;
if (gv<0)gv=0; else if (gv>255)gv=255;
if (bv<0)bv=0; else if (bv>255)bv=255;
*colout = RGB(rv,gv,bv);
return true;
}
bool SWELL_ChooseColor(HWND unused, COLORREF *a, int ncustom, COLORREF *custom)
{
NSColorPanel *pan=[NSColorPanel sharedColorPanel];
if (!pan||!a) return false;
NSColor *bkcol=[NSColor colorWithCalibratedRed:GetRValue(*a)/255.0f green:GetGValue(*a)/255.0f blue:GetBValue(*a)/255.0f alpha:1.0f];
[pan setColor:bkcol];
[pan setShowsAlpha:NO];
[pan setAccessoryView:nil];
HWND h = makeOKcancel((HWND)pan);
bool hadOK=!h;
NSModalSession ctx=[NSApp beginModalSessionForWindow:pan];
while ([NSApp runModalSession:ctx]==NSRunContinuesResponse && [pan isVisible])
{
const LONG_PTR res = h ? GetWindowLongPtr(h,0) : 0;
if (res) { hadOK=res==1; break; }
Sleep(3);
}
[NSApp endModalSession:ctx];
if (h)
{
SendMessage(h,WM_DESTROY,0,0);
[pan setAccessoryView:nil]; // will destroy h anyway
[pan close];
}
return hadOK && ColorFromNSColor([pan color],a);
}
bool SWELL_ChooseFont(HWND unused, LOGFONT *lf)
{
if (!lf) return false;
NSFontPanel *pan = [NSFontPanel sharedFontPanel];
int sz=lf->lfHeight > 0 ? lf->lfHeight : lf->lfHeight < 0 ? -lf->lfHeight : lf->lfWidth;
char buf[1024];
lstrcpyn_safe(buf,lf->lfFaceName,sizeof(buf));
if (lf->lfWeight >= FW_BOLD) lstrcatn(buf," Bold",sizeof(buf));
if (lf->lfItalic) lstrcatn(buf," Italic",sizeof(buf));
NSString *lbl=(NSString *)SWELL_CStringToCFString(buf);
NSFont *tmpfont = [NSFont fontWithName:lbl size:sz];
if (!tmpfont) tmpfont = [NSFont systemFontOfSize:sz];
[lbl release];
[pan setPanelFont:tmpfont isMultiple:NO];
[pan setAccessoryView:nil];
HWND h = makeOKcancel((HWND)pan);
bool hadOK=!h;
NSModalSession ctx=[NSApp beginModalSessionForWindow:pan];
while ([NSApp runModalSession:ctx]==NSRunContinuesResponse && [pan isVisible])
{
const LONG_PTR a = h ? GetWindowLongPtr(h,0) : 0;
if (a) { hadOK=a==1; break; }
Sleep(3);
}
[NSApp endModalSession:ctx];
if (h)
{
SendMessage(h,WM_DESTROY,0,0);
[pan setAccessoryView:nil]; // will destroy h
[pan close];
}
if (!hadOK) return false;
NSFont *newfont = [pan panelConvertFont:tmpfont];
int newsz = (int) ([newfont pointSize]+0.5);
LOGFONT oldf=*lf;
if (newsz != sz)
{
lf->lfWidth=0;
lf->lfHeight = newsz;
}
SWELL_CFStringToCString([newfont familyName],lf->lfFaceName, sizeof(lf->lfFaceName));
SWELL_CFStringToCString([newfont displayName],buf,sizeof(buf));
lf->lfItalic = !! strstr(buf,"Italic");
lf->lfWeight = strstr(buf,"Bold") ? FW_BOLD : FW_NORMAL;
return memcmp(lf,&oldf,sizeof(LOGFONT)) != 0;
}
#endif

View File

@@ -0,0 +1,150 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifdef SWELL_PROVIDED_BY_APP
#define SWELL_API_DEFPARM(x)
#define SWELL_API_DEFINE(ret,func,parms) ret (*func) parms ;
extern "C" {
#include "swell.h"
};
// only include this file in projects that are linked to libSwell.so
struct SWELL_CursorResourceIndex *SWELL_curmodule_cursorresource_head;
struct SWELL_DialogResourceIndex *SWELL_curmodule_dialogresource_head;
struct SWELL_MenuResourceIndex *SWELL_curmodule_menuresource_head;
// define the functions
static struct
{
const char *name;
void **func;
} api_tab[]={
#undef _WDL_SWELL_H_API_DEFINED_
#undef SWELL_API_DEFINE
#define SWELL_API_DEFINE(ret, func, parms) {#func, (void **)&func },
#include "swell.h"
};
static int dummyFunc() { return 0; }
static int doinit(void *(*GetFunc)(const char *name))
{
int errcnt=0;
for (int x = 0; x < (int)(sizeof(api_tab)/sizeof(api_tab[0])); x ++)
{
*api_tab[x].func=GetFunc(api_tab[x].name);
if (!*api_tab[x].func)
{
printf("SWELL API not found: %s\n",api_tab[x].name);
errcnt++;
*api_tab[x].func = (void*)&dummyFunc;
}
}
return errcnt;
}
#ifdef SWELL_LOAD_SWELL_DYLIB
static void *(*__loaded_getfunc)(const char *name)=NULL;
class SwellAPPInitializer
{
public:
SwellAPPInitializer()
{
void *(*SWELLAPI_GetFunc)(const char *name)=NULL;
char fn[4096];
const int nSize=sizeof(fn)-64;
int sz=readlink("/proc/self/exe",fn,nSize);
if (sz<1)
{
Dl_info inf={0,};
if (dladdr(&api_tab,&inf) && inf.dli_fname)
sz = (int) strlen(inf.dli_fname);
else
sz = 0;
}
if (sz>=nSize)sz=nSize-1;
fn[sz]=0;
char *p=fn;
while (*p) p++;
while (p >= fn && *p != '/') p--;
p++;
strcpy(p,p==fn ? "./libSwell.so" : "libSwell.so");
void *tmp = dlopen(fn,RTLD_LAZY);
if (!tmp)
{
printf("Error loading '%s': %s\n",fn,dlerror());
exit(2);
}
const char *preload_fn = (const char *)dlsym(tmp,"SWELL_WANT_LOAD_LIBRARY");
if (preload_fn && *preload_fn)
dlopen(preload_fn,RTLD_LAZY|RTLD_GLOBAL);
*(void **)&SWELLAPI_GetFunc = dlsym(tmp,"SWELLAPI_GetFunc");
if (SWELLAPI_GetFunc && SWELLAPI_GetFunc(NULL)==(void*)0x100)
{
void (*set_app_main)(INT_PTR (*AppMain)(int msg, INT_PTR parm1, INT_PTR parm2));
*(void **)&set_app_main = dlsym(tmp,"SWELL_set_app_main");
if (set_app_main) set_app_main(SWELLAppMain);
__loaded_getfunc = SWELLAPI_GetFunc;
if (doinit(SWELLAPI_GetFunc)) exit(1);
}
}
~SwellAPPInitializer()
{
}
};
SwellAPPInitializer m_swell_appAPIinit;
extern "C" __attribute__ ((visibility ("default"))) void *SWELLAPI_GetFunc(const char *name)
{
if (__loaded_getfunc) return __loaded_getfunc(name);
return NULL;
}
#else
extern "C" __attribute__ ((visibility ("default"))) int SWELL_dllMain(HINSTANCE hInst, DWORD callMode, LPVOID _GetFunc)
{
if (callMode == DLL_PROCESS_ATTACH)
{
if (!_GetFunc) return 0;
doinit((void *(*)(const char *)) _GetFunc);
}
// this returning 1 allows DllMain to be called, if available
return 1;
}
#endif
#endif

View File

@@ -0,0 +1,95 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifdef SWELL_PROVIDED_BY_APP
#import <Cocoa/Cocoa.h>
#import <objc/objc-runtime.h>
#define SWELL_API_DEFPARM(x)
#define SWELL_API_DEFINE(ret,func,parms) ret (*func) parms ;
#include "swell.h"
// only include this file in projects that are linked to swell.dylib
struct SWELL_DialogResourceIndex *SWELL_curmodule_dialogresource_head;
struct SWELL_MenuResourceIndex *SWELL_curmodule_menuresource_head;
// define the functions
static struct
{
const char *name;
void **func;
} api_tab[]={
#undef _WDL_SWELL_H_API_DEFINED_
#undef SWELL_API_DEFINE
#define SWELL_API_DEFINE(ret, func, parms) {#func, (void **)&func },
#include "swell-functions.h"
};
static int dummyFunc() { return 0; }
class SwellAPPInitializer
{
public:
SwellAPPInitializer()
{
void *(*SWELLAPI_GetFunc)(const char *name)=NULL;
void *(*send_msg)(id, SEL) = (void *(*)(id, SEL))objc_msgSend;
id del = [NSApp delegate];
if (del && [del respondsToSelector:@selector(swellGetAPPAPIFunc)])
*(void **)&SWELLAPI_GetFunc = send_msg(del,@selector(swellGetAPPAPIFunc));
if (!SWELLAPI_GetFunc) NSLog(@"SWELL API provider not found\n");
else if (SWELLAPI_GetFunc(NULL)!=(void*)0x100)
{
NSLog(@"SWELL API provider returned incorrect version\n");
SWELLAPI_GetFunc=0;
}
int x;
for (x = 0; x < sizeof(api_tab)/sizeof(api_tab[0]); x ++)
{
*api_tab[x].func=SWELLAPI_GetFunc?SWELLAPI_GetFunc(api_tab[x].name):0;
if (!*api_tab[x].func)
{
if (SWELLAPI_GetFunc) NSLog(@"SWELL API not found: %s\n",api_tab[x].name);
*api_tab[x].func = (void*)&dummyFunc;
}
}
}
~SwellAPPInitializer()
{
}
};
SwellAPPInitializer m_swell_appAPIinit;
extern "C" __attribute__ ((visibility ("default"))) int SWELL_dllMain(HINSTANCE hInst, DWORD callMode, LPVOID _GetFunc)
{
// this returning 1 allows DllMain to be called, if available
return 1;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
#ifndef _SWELL_WIN32_H_
#define _SWELL_WIN32_H_
/*************
** helpers to give swell-like functionality on win32
*/
#ifdef _WIN32
void SWELL_DisableContextMenu(HWND h, bool dis);
#ifndef SWELL_WIN32_DECLARE_ONLY
#include <windows.h>
#include "../wdltypes.h"
#define SWELL_DISABLE_CTX_OLDPROC_NAME "SWELLDisableCtxOldProc"
static LRESULT WINAPI swellDisableCtxNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HANDLE oldProc = uMsg != WM_CONTEXTMENU ? GetProp(hwnd,SWELL_DISABLE_CTX_OLDPROC_NAME) : NULL;
if (uMsg == WM_DESTROY)
{
RemoveProp(hwnd,SWELL_DISABLE_CTX_OLDPROC_NAME);
if (oldProc) SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LPARAM)oldProc);
}
return oldProc ? CallWindowProc((WNDPROC)oldProc,hwnd,uMsg,wParam,lParam) : DefWindowProc(hwnd,uMsg,wParam,lParam);
}
void SWELL_DisableContextMenu(HWND h, bool dis)
{
char classname[512];
if (WDL_NOT_NORMALLY(!h)) return;
if (GetClassName(h,classname,sizeof(classname)) && !strcmp(classname,"ComboBox"))
{
HWND h2 = FindWindowEx(h,NULL,"Edit",NULL);
if (h2) h = h2;
}
if (dis)
{
if (!GetProp(h,SWELL_DISABLE_CTX_OLDPROC_NAME))
SetProp(h,SWELL_DISABLE_CTX_OLDPROC_NAME,(HANDLE)SetWindowLongPtr(h,GWLP_WNDPROC,(LPARAM)swellDisableCtxNewWndProc));
}
else
{
LPARAM op = (LPARAM)GetProp(h,SWELL_DISABLE_CTX_OLDPROC_NAME);
if (op) SetWindowLongPtr(h,GWLP_WNDPROC,op);
RemoveProp(h,SWELL_DISABLE_CTX_OLDPROC_NAME);
}
}
#endif // !SWELL_WIN32_DECLARE_ONLY
#endif // _WIN32
#endif // _SWELL_WIN32_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,197 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
SWELL provides _EXTREMELY BASIC_ win32 wrapping for OS X and maybe other platforms.
*/
#ifndef _WIN32
#ifndef _WDL_SWELL_H_ // here purely for apps/other libraries (dirscan.h uses it), each section actually has its own define
#define _WDL_SWELL_H_
#if defined(__APPLE__) && !defined(SWELL_FORCE_GENERIC)
#define SWELL_TARGET_OSX
#define SWELL_TARGET_OSX_COCOA
#endif
// for swell*generic
// #define SWELL_TARGET_GDK
// #define SWELL_LICE_GDI
#endif
#ifdef __APPLE__
// go ahead and get this included before we define FSHIFT in swell-types.h
#include <sys/param.h>
#endif
// IF YOU ADD TO SWELL:
// Adding types, defines, etc: add to swell-types.h
// Adding functions: put them in swell-functions.h
#include "swell-types.h"
#include "swell-functions.h"
#ifndef SWELL_PROVIDED_BY_APP
#ifndef _WDL_SWELL_H_UTIL_DEFINED_
#define _WDL_SWELL_H_UTIL_DEFINED_
// these should never be called directly!!! put SWELL_POSTMESSAGE_DELEGATE_IMPL in your nsapp delegate, and call SWELL_POSTMESSAGE_INIT at some point from there too
#define SWELL_POSTMESSAGE_INIT SWELL_Internal_PostMessage_Init();
#define SWELL_POSTMESSAGE_DELEGATE_IMPL \
-(bool)swellPostMessage:(HWND)dest msg:(int)message wp:(WPARAM)wParam lp:(LPARAM)lParam { \
return SWELL_Internal_PostMessage(dest,message,wParam,lParam); \
} \
-(void)swellPostMessageClearQ:(HWND)dest { \
SWELL_Internal_PMQ_ClearAllMessages(dest); \
} \
-(void)swellPostMessageTick:(id)sender { \
SWELL_MessageQueue_Flush(); \
}
BOOL SWELL_Internal_PostMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void SWELL_Internal_PMQ_ClearAllMessages(HWND hwnd);
// if you use this then include swell-appstub.mm in your project
#define SWELL_APPAPI_DELEGATE_IMPL \
-(void *)swellGetAPPAPIFunc { \
void *SWELLAPI_GetFunc(const char *name); \
return (void*)SWELLAPI_GetFunc; \
}
#endif // _WDL_SWELL_H_UTIL_DEFINED_
#endif // !SWELL_PROVIDED_BY_APP
#endif // !_WIN32
#ifndef SWELL_TARGET_OSX
#ifndef SWELL_CB_InsertString
#define SWELL_CB_InsertString(hwnd, idx, pos, str) ((int)SendDlgItemMessage(hwnd,idx,CB_INSERTSTRING,(pos),(LPARAM)(str)))
#define SWELL_CB_AddString(hwnd, idx, str) ((int)SendDlgItemMessage(hwnd,idx,CB_ADDSTRING,0,(LPARAM)(str)))
#define SWELL_CB_SetCurSel(hwnd,idx,val) ((int)SendDlgItemMessage(hwnd,idx,CB_SETCURSEL,(WPARAM)(val),0))
#define SWELL_CB_GetNumItems(hwnd,idx) ((int)SendDlgItemMessage(hwnd,idx,CB_GETCOUNT,0,0))
#define SWELL_CB_GetCurSel(hwnd,idx) ((int)SendDlgItemMessage(hwnd,idx,CB_GETCURSEL,0,0))
#define SWELL_CB_SetItemData(hwnd,idx,item,val) SendDlgItemMessage(hwnd,idx,CB_SETITEMDATA,(item),(val))
#define SWELL_CB_GetItemData(hwnd,idx,item) SendDlgItemMessage(hwnd,idx,CB_GETITEMDATA,(item),0)
#define SWELL_CB_GetItemText(hwnd,idx,item,buf,bufsz) SendDlgItemMessage(hwnd,idx,CB_GETLBTEXT,(item),(LPARAM)(buf))
#define SWELL_CB_Empty(hwnd,idx) SendDlgItemMessage(hwnd,idx,CB_RESETCONTENT,0,0)
#define SWELL_CB_DeleteString(hwnd,idx,str) SendDlgItemMessage(hwnd,idx,CB_DELETESTRING,str,0)
#define SWELL_TB_SetPos(hwnd, idx, pos) SendDlgItemMessage(hwnd,idx, TBM_SETPOS,TRUE,(pos))
#define SWELL_TB_SetRange(hwnd, idx, low, hi) SendDlgItemMessage(hwnd,idx,TBM_SETRANGE,TRUE,(LPARAM)MAKELONG((low),(hi)))
#define SWELL_TB_GetPos(hwnd, idx) ((int)SendDlgItemMessage(hwnd,idx,TBM_GETPOS,0,0))
#define SWELL_TB_SetTic(hwnd, idx, pos) SendDlgItemMessage(hwnd,idx,TBM_SETTIC,0,(pos))
#endif
#endif// !SWELL_TARGET_OSX
#ifndef WDL_GDP_CTX // stupid GDP compatibility layer, deprecated
#define WDL_GDP_CTX HDC
#define WDL_GDP_PEN HPEN
#define WDL_GDP_BRUSH HBRUSH
#define WDL_GDP_CreatePen(col, wid) (WDL_GDP_PEN)CreatePen(PS_SOLID,(wid),(col))
#define WDL_GDP_DeletePen(pen) DeleteObject((HGDIOBJ)(pen))
#define WDL_GDP_SetPen(ctx, pen) ((WDL_GDP_PEN)SelectObject(ctx,(HGDIOBJ)(pen)))
#define WDL_GDP_SetBrush(ctx, brush) ((WDL_GDP_BRUSH)SelectObject(ctx,(HGDIOBJ)(brush)))
#define WDL_GDP_CreateBrush(col) (WDL_GDP_BRUSH)CreateSolidBrush(col)
#define WDL_GDP_DeleteBrush(brush) DeleteObject((HGDIOBJ)(brush))
#define WDL_GDP_FillRectWithBrush(hdc,r,br) FillRect(hdc,r,(HBRUSH)(br))
#define WDL_GDP_Rectangle(hdc,l,t,r,b) Rectangle(hdc,l,t,r,b)
#define WDL_GDP_Polygon(hdc,pts,n) Polygon(hdc,pts,n)
#define WDL_GDP_MoveToEx(hdc,x,y,op) MoveToEx(hdc,x,y,op)
#define WDL_GDP_LineTo(hdc,x,y) LineTo(hdc,x,y)
#define WDL_GDP_PutPixel(hdc,x,y,c) SetPixel(hdc,x,y,c)
#define WDL_GDP_PolyBezierTo(hdc,p,np) PolyBezierTo(hdc,p,np)
#define SWELL_SyncCtxFrameBuffer(x) // no longer used
#endif
#if !defined(SWELL_AUTORELEASE_HELPER_DEFINED) && defined(__cplusplus) && (!defined(SWELL_TARGET_OSX) || defined(SWELL_API_DEFINE))
#define SWELL_AUTORELEASE_HELPER_DEFINED
class SWELL_AutoReleaseHelper // no-op on non-apple
{
#ifdef SWELL_TARGET_OSX
void *m_arp;
#endif
public:
SWELL_AutoReleaseHelper()
{
#ifdef SWELL_TARGET_OSX
m_arp = SWELL_InitAutoRelease();
#endif
}
~SWELL_AutoReleaseHelper()
{
#ifdef SWELL_TARGET_OSX
release();
#endif
}
void release()
{
#ifdef SWELL_TARGET_OSX
if (m_arp) { SWELL_QuitAutoRelease(m_arp); m_arp=NULL; }
#endif
}
};
#endif
#if defined(_WIN32) && !defined(LoadLibraryGlobals)
#define LoadLibraryGlobals(a,b) LoadLibrary(a)
#endif
#ifndef SWELLAPP_ONLOAD
#define SWELLAPP_ONLOAD 0x0001 // initialization of app vars etc
#define SWELLAPP_LOADED 0x0002 // create dialogs etc
#define SWELLAPP_DESTROY 0x0003 // about to destroy (cleanup etc)
#define SWELLAPP_SHOULDDESTROY 0x0004 // return 0 to allow app to terminate, >0 to prevent
#define SWELLAPP_OPENFILE 0x0050 // parm1= (const char *)string, return >0 if allowed
#define SWELLAPP_NEWFILE 0x0051 // new file, return >0 if allowed
#define SWELLAPP_SHOULDOPENNEWFILE 0x0052 // allow opening new file? >0 if allowed
#define SWELLAPP_ONCOMMAND 0x0099 // parm1 = (int) command ID, parm2 = (id) sender
#define SWELLAPP_PROCESSMESSAGE 0x0100 // parm1=(MSG *)msg (loosely), parm2= (NSEvent *) the event . return >0 to eat
#define SWELLAPP_ACTIVATE 0x1000 // parm1 = (bool) isactive. return nonzero to prevent WM_ACTIVATEAPP from being broadcasted
#endif

View File

@@ -0,0 +1,357 @@
#!/usr/bin/php
<?php
if (!function_exists('file_put_contents')) {
function file_put_contents($filename, $data, $lockflag) {
$f = @fopen($filename, 'w');
if (!$f) {
return false;
} else {
$bytes = fwrite($f, $data);
fclose($f);
return $bytes;
}
}
}
function convertquotes($in)
{
$ret = "";
$qs= 0;
for ($x=0;$x<strlen($in); $x++)
{
if ($in[$x] == '"')
{
if (!$qs)
{
$qs=1;
}
else
{
$qs=0;
if ($x < strlen($in) && $in[$x+1] == '"')
{
$ret .= "\\";
continue;
}
}
}
$ret .= $in[$x];
}
return $ret;
}
function utf_fgets($fp, &$state)
{
if ($state==0)
{
$state = -1;
$s = fread($fp,2);
if (ord($s[0])==0xff && ord($s[1]) == 0xfe) $state=1; // UTF-16LE
else if (ord($s[0])==0xfe && ord($s[1]) == 0xff) $state=2; // UTF-16BE
else if (ord($s[0])==0xef && ord($s[1]) == 0xbb)
{
$s2 = fread($fp,1);
if (ord($s2[0]) != 0xbf) return $s . $s2 . fgets($fp,4096);
}
}
if ($state < 0) return fgets($fp,4096);
$ret = "";
while ($s = fread($fp,2))
{
if ($state == 1) $s = ord($s[0]) | (ord($s[1])<<8);
else $s = ord($s[1]) | (ord($s[0])<<8);
if ($s < 128)
{
$ret .= chr($s);
if ($s == ord("\n")) break;
}
else if ($s <= 0x7ff) $ret .= chr(0xc0 | (($s>>6)&0x1f)) . chr(0x80 | ($s&0x3f));
else $ret .= chr(0xe0 | (($s>>12)&0xf)) . chr(0x80 | (($s)>>6)&0x3f) . chr(0x80 | ($s&0x3f));
}
return $ret;
}
function swell_rc2cpp_dialog($fp) // returns array with ["data"] and optionally ["error"]
{
fseek($fp,0,SEEK_SET);
$utf_state=0;
$errstr="";
$retstr = "";
$retstr .= '#ifndef SWELL_DLG_SCALE_AUTOGEN' . "\n";
$retstr .= '#ifdef __APPLE__' . "\n";
$retstr .= ' #define SWELL_DLG_SCALE_AUTOGEN 1.7' . "\n";
$retstr .= '#else' . "\n";
$retstr .= ' #define SWELL_DLG_SCALE_AUTOGEN 1.9' . "\n";
$retstr .= '#endif' . "\n";
$retstr .= '#endif' . "\n";
$retstr .= '#ifndef SWELL_DLG_FLAGS_AUTOGEN' . "\n";
$retstr .= '#define SWELL_DLG_FLAGS_AUTOGEN SWELL_DLG_WS_FLIPPED|SWELL_DLG_WS_NOAUTOSIZE' . "\n";
$retstr .= "#endif\n";
$retstr .= "\n";
$dlg_state=0; // 1 = before BEGIN, 2=after BEGIN
$dlg_name="";
$dlg_size_w=0;
$dlg_size_h=0;
$dlg_title = "";
$dlg_styles = "SWELL_DLG_FLAGS_AUTOGEN";
$dlg_contents="";
$next_line="";
for (;;)
{
if ($next_line != "") { $x=$next_line; $next_line =""; }
else if (!($x=utf_fgets($fp,$utf_state))) break;
$x = convertquotes($x);
$y=trim($x);
if ($dlg_state>=2)
{
if (preg_match("/^LTEXT(.*), *WS_EX_RIGHT$/",$y,$match)) $y = "RTEXT" . $match[1];
$dlg_contents .= $y . "\n";
if ($y == "END")
{
if ($dlg_state==2) $dlg_styles.="|SWELL_DLG_WS_OPAQUE";
$retstr .= "#ifndef SET_$dlg_name" . "_SCALE\n";
$retstr .= "#define SET_$dlg_name" . "_SCALE SWELL_DLG_SCALE_AUTOGEN\n";
$retstr .= "#endif\n";
$retstr .= "#ifndef SET_$dlg_name" . "_STYLE\n";
$retstr .= "#define SET_$dlg_name" . "_STYLE $dlg_styles\n";
$retstr .= "#endif\n";
$retstr .= "SWELL_DEFINE_DIALOG_RESOURCE_BEGIN($dlg_name,SET_$dlg_name" . "_STYLE,\"$dlg_title\",$dlg_size_w,$dlg_size_h,SET_$dlg_name" . "_SCALE)\n";
$dlg_contents=str_replace("NOT WS_VISIBLE","SWELL_NOT_WS_VISIBLE",$dlg_contents);
$dlg_contents=str_replace("NOT\nWS_VISIBLE","SWELL_NOT_WS_VISIBLE",$dlg_contents);
$dlg_contents=str_replace("NOT \nWS_VISIBLE","SWELL_NOT_WS_VISIBLE",$dlg_contents);
$retstr .= $dlg_contents;
$retstr .= "SWELL_DEFINE_DIALOG_RESOURCE_END($dlg_name)\n\n\n";
$dlg_state=0;
}
else if (strlen($y)>1) $dlg_state=3;
}
else
{
$parms = explode(" ", $y);
if (count($parms) > 0)
{
if ($dlg_state == 0)
{
// if (substr($parms[0],0,8) == "IDD_PREF")
if (count($parms)>4 && ($parms[1] == 'DIALOGEX'||$parms[1] == 'DIALOG'))
{
$dlg_name=$parms[0];
$rdidx = 2;
if ($parms[$rdidx] == 'DISCARDABLE') $rdidx++;
while ($parms[$rdidx] == "" && $rdidx < count($parms)) $rdidx++;
$rdidx += 2;
$dlg_size_w = str_replace(",","",$parms[$rdidx++]);
$dlg_size_h = str_replace(",","",$parms[$rdidx++]);
if (count($parms) >= $rdidx && $dlg_size_w != "" && $dlg_size_h != "")
{
$dlg_title="";
$dlg_styles="SWELL_DLG_FLAGS_AUTOGEN";
$dlg_contents="";
$dlg_state=1;
}
else $errstr .= "WARNING: corrupted $dlg_name resource\n";
}
}
else if ($dlg_state == 1)
{
if ($parms[0] == "BEGIN")
{
$dlg_state=2;
$dlg_contents = $y ."\n";
}
else
{
if ($parms[0] == "CAPTION")
{
$dlg_title = str_replace("\"","",trim(substr($y,8)));
}
else if ($parms[0] == "STYLE" || $parms[0] == "EXSTYLE")
{
$rep=0;
for (;;)
{
$next_line = utf_fgets($fp,$utf_state);
if (!($next_line )) { $next_line=""; break; }
if (substr($next_line,0,1)==" " || substr($next_line,0,1)=="\t")
{
$y .= " " . trim(convertquotes($next_line));
$rep++;
$next_line="";
}
else break;
}
if ($rep) $parms = explode(" ", $y);
$opmode=0;
$rdidx=1;
while ($rdidx < count($parms))
{
if ($parms[$rdidx] == '|') { $opmode=0; }
else if ($parms[$rdidx] == 'NOT') { $opmode=1; }
else if ($parms[$rdidx] == 'WS_CHILD')
{
if (!$opmode) $dlg_styles .= "|SWELL_DLG_WS_CHILD";
}
else if ($parms[$rdidx] == 'WS_THICKFRAME')
{
if (!$opmode) $dlg_styles .= "|SWELL_DLG_WS_RESIZABLE";
}
else if ($parms[$rdidx] == 'WS_EX_ACCEPTFILES')
{
if (!$opmode) $dlg_styles .= "|SWELL_DLG_WS_DROPTARGET";
}
else if ($parms[$rdidx] == 'WS_CLIPSIBLINGS')
{
if (!$opmode) $dlg_styles .= "|WS_CLIPSIBLINGS";
}
else $opmode=0;
$rdidx++;
}
}
}
}
}
}
}
if ($dlg_state != 0)
$errstr .= "WARNING: there may have been a truncated dialog resource ($dlg_name)\n";
$retstr .= "\n//EOF\n\n";
$rv = array();
$rv["data"] = $retstr;
$rv["error"] = $errstr;
return $rv;
}
function swell_rc2cpp_menu($fp) // returns array with ["data"] and optionally ["error"]
{
$retstr="";
$errstr="";
fseek($fp,0,SEEK_SET);
$utf_state=0;
$menu_symbol="";
$menu_depth=0;
while (($x=utf_fgets($fp,$utf_state)))
{
$x = convertquotes($x);
$y=trim($x);
if ($menu_symbol == "")
{
$parms = explode(" ", $y);
$tok = "MENU";
if (count($parms) >= 2 && $parms[1] == $tok)
{
$menu_symbol = $parms[0];
$menu_depth=0;
$retstr .= "SWELL_DEFINE_MENU_RESOURCE_BEGIN($menu_symbol)\n";
}
}
else
{
if ($y == "END")
{
$menu_depth-=1;
if ($menu_depth == 0)
{
$retstr .= "SWELL_DEFINE_MENU_RESOURCE_END($menu_symbol)\n\n\n";
}
if ($menu_depth < 1) $menu_symbol="";
}
if ($menu_depth>0)
{
if (substr($y,-strlen(", HELP")) == ", HELP")
{
$x=substr(rtrim($x),0,-strlen(", HELP")) . "\n";
}
$retstr .= $x;
}
if ($y == "BEGIN") $menu_depth+=1;
}
}
$retstr .= "\n//EOF\n\n";
$rv = array();
$rv["data"] = $retstr;
$rv["error"] = $errstr;
return $rv;
}
if (count($argv)<2) die("usage: swell_resgen.php [--force] file.rc ...\n");
$x=1;
$forcemode = 0;
if ($argv[$x] == "--force") { $forcemode=1; $x++; }
$lp = dirname(__FILE__);
$proc=0;
$skipped=0;
$err=0;
$quiet=0;
for (; $x < count($argv); $x ++)
{
$srcfn = $argv[$x];
if ($srcfn == "--quiet")
{
$quiet = 1;
continue;
}
if (!stristr($srcfn,".rc") || !($fp = @fopen($srcfn,"r")))
{
$err++;
echo "$srcfn: not valid or not found!\n";
continue;
}
$ofnmenu = $srcfn . "_mac_menu";
$ofndlg = $srcfn . "_mac_dlg";
$res = swell_rc2cpp_dialog($fp);
$res2 = swell_rc2cpp_menu($fp);
fclose($fp);
if ($res["error"] != "" || $res2["error"] != "")
{
$err++;
echo "$srcfn: error";
if ($res["error"] != "") echo " dialog: " . $res["error"];
if ($res2["error"] != "") echo " menu: " . $res2["error"];
echo "\n";
continue;
}
$f="";
if ($forcemode || !file_exists($ofndlg) || file_get_contents($ofndlg) != $res["data"])
{
$f .= "dlg updated";
if (!file_put_contents($ofndlg,$res["data"],LOCK_EX)) { echo "error writing $ofndlg\n"; $err++; }
}
if ($forcemode || !file_exists($ofnmenu) || file_get_contents($ofnmenu) != $res2["data"])
{
if ($f != "") $f .= ", ";
$f .= "menu updated";
if (!file_put_contents($ofnmenu,$res2["data"],LOCK_EX)) { echo "error writing $ofnmenu\n"; $err++; }
}
if ($f != "")
{
$proc++;
}
else
{
$skipped++;
$f = "skipped";
}
if (!$quiet) echo "$srcfn: $f\n";
}
if (!$quiet || $err) echo "processed $proc, skipped $skipped, error $err\n";
?>

View File

@@ -0,0 +1,361 @@
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw(:seek :flock);
my @input;
my %style_xlate = (
"WS_CHILD" => "SWELL_DLG_WS_CHILD",
"WS_THICKFRAME" => "SWELL_DLG_WS_RESIZABLE",
"WS_EX_ACCEPTFILES" => "SWELL_DLG_WS_DROPTARGET",
"WS_CLIPSIBLINGS" => "WS_CLIPSIBLINGS",
);
sub update_file {
my($fn, $force, $data) = @_;
open(FPC_FH, '+>>', $fn) or return $!;
if (!flock(FPC_FH, LOCK_EX)) {
close(FPC_FH);
return "error locking file";
}
seek FPC_FH, 0, SEEK_SET;
if ($force == 0)
{
my $v = "";
while (<FPC_FH>) { $v .= $_; }
if ($v eq $data) {
close(FPC_FH);
return "";
}
seek FPC_FH, 0, SEEK_SET;
}
truncate FPC_FH, 0;
print FPC_FH $data;
flock(FPC_FH, LOCK_UN);
close(FPC_FH);
return "OK";
}
sub convertquotes {
return $_[0] unless $_[0] =~ /"/;
my @a = split(/"/,$_[0], -1);
my $ret = $a[0];
my $qs = 0;
for (my $x=1;$x<@a; $x++) {
my $s = $a[$x];
if ($s eq "" && $qs && $x+1 < @a) {
$ret .= '\\"' . $a[++$x];
} else {
$ret .= "\"$s";
$qs = !$qs;
}
}
return $ret;
}
sub swell_rc2cpp_dialog
{
my $errstr = "";
my $retstr = '#ifndef SWELL_DLG_SCALE_AUTOGEN
#ifdef __APPLE__
#define SWELL_DLG_SCALE_AUTOGEN 1.7
#else
#define SWELL_DLG_SCALE_AUTOGEN 1.9
#endif
#endif
#ifndef SWELL_DLG_FLAGS_AUTOGEN
#define SWELL_DLG_FLAGS_AUTOGEN SWELL_DLG_WS_FLIPPED|SWELL_DLG_WS_NOAUTOSIZE
#endif
';
my $dlg_state=0; # 1 = before BEGIN, 2=after BEGIN
my $dlg_name="";
my $dlg_size_w=0;
my $dlg_size_h=0;
my $dlg_title = "";
my $dlg_styles = "SWELL_DLG_FLAGS_AUTOGEN";
my $dlg_contents="";
for (my $idx = 0; $idx < @input; $idx++)
{
my $x = $input[$idx];
(my $y = $x) =~ s/^\s+|\s+$//g;
if ($dlg_state>=2)
{
$y = "RTEXT" . $1 if $y =~ /^LTEXT(.*), *WS_EX_RIGHT$/;
if ($dlg_contents =~ /, *\n$/)
{
$dlg_contents =~ s/ *\n$//;
}
elsif ($dlg_contents =~ /[|] *\n$/)
{
$dlg_contents =~ s/ *\n$/ /;
}
elsif ($dlg_contents =~ /NOT *\n$/)
{
$dlg_contents =~ s/NOT *\n$/NOT /;
}
$dlg_contents .= $y . "\n";
if ($y eq "END")
{
if ($dlg_state==2) { $dlg_styles.="|SWELL_DLG_WS_OPAQUE" };
$retstr .= "#ifndef SET_${dlg_name}_SCALE\n" .
"#define SET_${dlg_name}_SCALE SWELL_DLG_SCALE_AUTOGEN\n" .
"#endif\n" .
"#ifndef SET_${dlg_name}_STYLE\n" .
"#define SET_${dlg_name}_STYLE $dlg_styles\n" .
"#endif\n" .
"SWELL_DEFINE_DIALOG_RESOURCE_BEGIN($dlg_name,SET_${dlg_name}_STYLE,\"$dlg_title\",$dlg_size_w,$dlg_size_h,SET_${dlg_name}_SCALE)\n";
$dlg_contents =~ s/NOT\s+WS_VISIBLE/SWELL_NOT_WS_VISIBLE/gs;
$retstr .= $dlg_contents;
$retstr .= "SWELL_DEFINE_DIALOG_RESOURCE_END($dlg_name)\n\n\n";
$dlg_state=0;
}
elsif (length($y)>1) { $dlg_state=3; }
}
else
{
my @parms = split " ", $y;
if (@parms > 0)
{
if ($dlg_state == 0)
{
if (@parms>4 && ($parms[1] eq "DIALOGEX" || $parms[1] eq "DIALOG"))
{
$dlg_name=$parms[0];
my $rdidx = 2;
if ($parms[$rdidx] eq 'DISCARDABLE') { $rdidx++ };
while ($rdidx < @parms && $parms[$rdidx] eq "") { $rdidx++; }
$rdidx += 2;
($dlg_size_w = $parms[$rdidx++]) =~ s/,//g;
($dlg_size_h = $parms[$rdidx++]) =~ s/,//g;
if (@parms >= $rdidx && $dlg_size_w ne "" && $dlg_size_h ne "")
{
$dlg_title="";
$dlg_styles="SWELL_DLG_FLAGS_AUTOGEN";
$dlg_contents="";
$dlg_state=1;
}
else
{
$errstr .= "WARNING: corrupted $dlg_name resource\n";
}
}
}
elsif ($dlg_state == 1)
{
if ($parms[0] eq "BEGIN")
{
$dlg_state=2;
$dlg_contents = $y ."\n";
}
else
{
if ($parms[0] eq "CAPTION")
{
$dlg_title = substr $y, 8;
$dlg_title =~ s/^\s+|\s+$|"//g;
}
elsif ($parms[0] eq "STYLE" || $parms[0] eq "EXSTYLE")
{
my $rep=0;
for (;($idx+1) < @input; $idx++)
{
my $next_line = $input[$idx+1];
last unless $next_line =~ /^[ \t]/;
$next_line =~ s/^\s+|\s+$//g;
$y .= " " . $next_line;
$rep++;
}
@parms = split " ", $y if $rep;
my $opmode=0;
for (my $rdidx = 1; $rdidx < @parms; $rdidx ++)
{
if ($parms[$rdidx] eq "NOT") { $opmode=1; }
elsif ($opmode == 0)
{
my $s = $style_xlate{$parms[$rdidx]};
$dlg_styles .= "|$s" if defined($s);
}
else { $opmode=0; }
}
}
}
}
}
}
}
$errstr .= "WARNING: there may have been a truncated dialog resource ($dlg_name)\n" if $dlg_state != 0;
$retstr .= "\n//EOF\n\n";
return ( $retstr, $errstr );
}
sub swell_rc2cpp_menu
{
my $retstr="";
my $errstr="";
my $menu_symbol="";
my $menu_depth=0;
for (@input)
{
my $x = $_;
(my $y = $x) =~ s/^\s+|\s+$//g;
if ($menu_symbol eq "")
{
my @parms = split " ", $y;
if (@parms >= 2 && $parms[1] eq "MENU")
{
$menu_symbol = $parms[0];
$menu_depth=0;
$retstr .= "SWELL_DEFINE_MENU_RESOURCE_BEGIN($menu_symbol)\n";
}
}
else
{
if ($y eq "END")
{
$menu_depth-=1;
if ($menu_depth == 0)
{
$retstr .= "SWELL_DEFINE_MENU_RESOURCE_END($menu_symbol)\n\n\n";
}
$menu_symbol="" if $menu_depth < 1;
}
if ($menu_depth>0)
{
if (($retstr =~ /,\s*$/) || ($x =~ /^\s*,/)) {
$retstr =~ s/\s*\n$//;
$x =~ s/^\s*//;
}
$x =~ s/, HELP\s*/\n/;
$retstr .= $x;
}
$menu_depth+=1 if $y eq "BEGIN";
}
}
$retstr .= "\n//EOF\n\n";
return ($retstr, $errstr);
}
die("usage: swell_resgen.pl [--force] file.rc ...\n") if @ARGV<1;
my $forcemode = 0;
my $proc=0;
my $skipped=0;
my $err=0;
my $quiet=0;
for (my $x = 0; $x < @ARGV; $x ++)
{
my $srcfn = $ARGV[$x];
if ($srcfn eq "--quiet")
{
$quiet = 1;
next;
}
if ($srcfn eq "--force")
{
$forcemode = 1;
next;
}
if (!($srcfn =~ /[.]rc$/i))
{
$err++;
print "$srcfn: does not end in .rc!\n";
next;
}
if (!open(UTF_FH, "<", $srcfn))
{
$err++;
print "$srcfn: could not open!\n";
continue;
}
$_ = <UTF_FH>;
if (/^\xff\xfe/ || /^\xfe\xff/) {
@input = ( );
my $order = (ord($_) == 0xff) ? 0 : 1;
seek UTF_FH, 2, SEEK_SET;
my $ret = "";
while (read UTF_FH, my $s, 2)
{
$s = ($order == 1) ? (ord($s) | (ord(substr($s,1))<<8)) : (ord(substr($s,1)) | (ord($s)<<8));
if ($s < 128) {
$ret .= chr($s);
if ($s == ord("\n")) {
push(@input,convertquotes($ret));
$ret = "";
}
}
elsif ($s <= 0x7ff) {
$ret .= chr(0xc0 | (($s>>6)&0x1f)) . chr(0x80 | ($s&0x3f));
}
else {
$ret .= chr(0xe0 | (($s>>12)&0xf)) . chr(0x80 | (($s)>>6)&0x3f) . chr(0x80 | ($s&0x3f));
}
}
push(@input,convertquotes($ret)) if $ret ne "";
} else {
$_ = substr($_,3) if /^\xef\xbb\xbf/;
@input = ( $_ );
while (<UTF_FH>) {
push @input, convertquotes($_);
}
}
close(UTF_FH);
my $ofnmenu = $srcfn . "_mac_menu";
my $ofndlg = $srcfn . "_mac_dlg";
my ($dlg_str, $dlg_err) = swell_rc2cpp_dialog();
my ($menu_str, $menu_err) = swell_rc2cpp_menu();
if ($dlg_err ne "" || $menu_err ne "")
{
$err++;
print "$srcfn: error";
print " dialog: $dlg_err" if $dlg_err ne "";
print " menu: $menu_err" if $menu_err ne "";
print "\n";
continue;
}
my $f="";
my $ok = update_file($ofndlg, $forcemode, $dlg_str);
$f .= ", dlg updated" if $ok eq "OK";
if ($ok ne "OK" && $ok ne "") { print "error writing $ofndlg: $ok\n"; $err++; }
$ok = update_file($ofnmenu, $forcemode, $menu_str);
$f .= ", menu updated" if $ok eq "OK";
if ($ok ne "OK" && $ok ne "") { print "error writing $ofnmenu: $ok\n"; $err++; }
if ($f ne "")
{
$f =~ s/^, //;
$proc++;
}
else
{
$skipped++;
$f = "skipped";
}
print "$srcfn: $f\n" if $quiet == 0;
}
print "processed $proc, skipped $skipped, error $err\n" if $quiet==0 || $err>0;

View File

@@ -0,0 +1,6 @@
#!/bin/sh
DIR="$(dirname $0)"
if [ "v$DIR" = "v" ]; then DIR=. ; fi
"$DIR/swell_resgen.pl" $*

View File

@@ -0,0 +1,14 @@
#import <Cocoa/Cocoa.h>
@interface SWELLApplication : NSApplication {
}
- (void)sendEvent:(NSEvent *)anEvent;
@end
@interface SWELLAppController : NSObject {
}
-(IBAction)onSysMenuCommand:(id)sender;
@end

View File

@@ -0,0 +1,252 @@
/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
Copyright (C) 2006 and later, Cockos, Inc.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#import "swellappmain.h"
#include "swell.h"
#include "swell-internal.h"
HMENU SWELL_app_stocksysmenu; // exposed to app, simply the contents of the default system menu (as defined in the nib)
static bool IsMultiLineEditControl(NSView *cv, id fs)
{
if (fs && [fs isKindOfClass:[NSTextView class]])
{
NSTextView *v = (NSTextView *)fs;
if ([v isEditable])
{
NSView *a=[v superview];
while (a && a != cv)
{
if ([a isKindOfClass:[NSTextField class]]) return false;
a = [a superview];
}
return true;
}
}
return false;
}
@implementation SWELLApplication
- (void)sendEvent:(NSEvent *)anEvent
{
NSEventType etype = [anEvent type];
if (etype == NSKeyUp)
{
// toss keyup if next keydown is the same key
NSEvent *nextDown = [self nextEventMatchingMask:NSKeyDownMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.003] inMode:NSDefaultRunLoopMode dequeue:FALSE];
if (nextDown && [nextDown keyCode] == [anEvent keyCode]) return;
}
else if (etype == NSKeyDown)
{
NSEvent *nextDown = [self nextEventMatchingMask:NSKeyDownMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.003] inMode:NSDefaultRunLoopMode dequeue:FALSE];
if (nextDown && [nextDown keyCode] == [anEvent keyCode])
{
#if 0
// no need to check timestamps -- if a queued key is there, just ignore this one(prevent a backlog)
static double sc=0.0;
if (sc == 0.0)
{
struct mach_timebase_info inf={0,};
mach_timebase_info(&inf);
if (inf.numer && inf.denom) sc = inf.numer / (inf.denom * 1000.0 * 1000.0 * 1000.0);
}
if (sc != 0.0 && [anEvent timestamp] < (double) mach_absolute_time() * sc - 0.05)
#endif
return;
}
}
NSWindow *modalWindow = [NSApp modalWindow];
NSWindow *focwnd=[anEvent window];
NSView *dest_view=NULL; // only valid when key message
if (etype==NSKeyDown||etype==NSKeyUp)
{
const UINT msgtype = etype==NSKeyDown ? WM_KEYDOWN : WM_KEYUP;
int flag,code=SWELL_MacKeyToWindowsKey(anEvent,&flag);
if (focwnd)
{
if (flag&(FCONTROL|FALT))
{
NSWindow *f = focwnd;
// handle carbon windows, sending all cmd/alt modified keys to their parent NSView (to be handled later)
// perhaps it'd be good to have a flag on these to see if they want it .. i.e. SWELL_SetCarbonHostView_WantKeyFlgs()..
while (f)
{
if ((dest_view=(NSView *)[f delegate]) && [dest_view respondsToSelector:@selector(swellIsCarbonHostingView)] && [(SWELL_hwndCarbonHost*)dest_view swellIsCarbonHostingView])
{
focwnd = [dest_view window];
break;
}
dest_view=0;
f=[f parentWindow];
}
}
if (!dest_view) // get default dest_view, and validate it as a NSView
{
if ((dest_view=(NSView *)[focwnd firstResponder]) && ![dest_view isKindOfClass:[NSView class]]) dest_view=NULL;
}
}
if (!modalWindow && (!focwnd || dest_view))
{
MSG msg={(HWND)dest_view,msgtype,(WPARAM)code,(LPARAM)flag}; // LPARAM is treated differently (giving modifier flags/FVIRTKEY etc) in sWELL's WM_KEYDOWN than in windows, deal with it
if (SWELLAppMain(SWELLAPP_PROCESSMESSAGE,(INT_PTR)&msg,(INT_PTR)anEvent)>0) return;
}
}
// default window handling:
if (etype == NSKeyDown && focwnd && dest_view)
{
NSView *cv = [focwnd contentView];
if (cv && [cv respondsToSelector:@selector(onSwellMessage:p1:p2:)]) //only work for swell windows
{
int flag,code=SWELL_MacKeyToWindowsKey(anEvent,&flag);
int cmdid=0;
// todo: other keys (such as shift+insert?)
if (((flag&~FVIRTKEY)==FCONTROL && (code=='V'||code=='C' ||code=='X')) && [dest_view isKindOfClass:[NSText class]])
{
if (code=='V') [(NSText *)dest_view paste:(id)cv];
else if (code=='C') [(NSText *)dest_view copy:(id)cv];
else if (code=='X') [(NSText *)dest_view cut:(id)cv];
return;
}
if ((!(flag&~(FVIRTKEY|FSHIFT)) && code == VK_ESCAPE) ||
((flag&~FVIRTKEY)==FCONTROL && code=='W'))
{
if (code == 'W') cmdid= IDCANCEL; // cmd+w always idcancel's
else if (!dest_view || ![dest_view isKindOfClass:[NSTextView class]]) cmdid=IDCANCEL; // not text view, idcancel
else if (!(flag&FSHIFT) && !IsMultiLineEditControl(cv,dest_view)) cmdid=IDCANCEL; // if singleline edit and shift not set, idcancel
if (!cmdid)
{
SetFocus((HWND)cv);
return;
}
}
else if (!(flag&0xff&~FVIRTKEY) && code == VK_RETURN)
{
// get default button command id, if any, if enabled
if (!IsMultiLineEditControl(cv,dest_view))
{
cmdid = SWELL_GetDefaultButtonID((HWND)cv,true);
if (!cmdid) // no action, set focus to parent
{
SetFocus((HWND)cv);
return;
}
}
}
if (cmdid)
{
SendMessage((HWND)cv,WM_COMMAND,cmdid,0);
return;
}
} // is swell CV
} // key down
[super sendEvent:anEvent];
}
@end
@implementation SWELLAppController
- (void)awakeFromNib
{
SWELL_EnsureMultithreadedCocoa();
[NSApp setDelegate:(id) self];
SWELL_POSTMESSAGE_INIT
HMENU stockMenu=(HMENU)[NSApp mainMenu];
if (stockMenu)
{
HMENU nf = GetSubMenu(stockMenu,0);
if (nf) SWELL_app_stocksysmenu = SWELL_DuplicateMenu(nf);
}
SWELLAppMain(SWELLAPP_ONLOAD,0,0);
}
-(IBAction)onSysMenuCommand:(id)sender
{
INT_PTR a = (INT_PTR) [(NSMenuItem *)sender tag];
if (a) SWELLAppMain(SWELLAPP_ONCOMMAND,a,(INT_PTR)sender);
}
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
char buf[4096];
buf[0]=0;
SWELL_CFStringToCString(filename,buf,sizeof(buf));
return buf[0] && SWELLAppMain(SWELLAPP_OPENFILE,(INT_PTR)buf,0)>0;
}
- (BOOL)applicationOpenUntitledFile:(NSApplication *)theApplication
{
return SWELLAppMain(SWELLAPP_NEWFILE,0,0)>0;
}
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
return SWELLAppMain(SWELLAPP_SHOULDOPENNEWFILE,0,0)>0;
}
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
SWELLAppMain(SWELLAPP_LOADED,0,0);
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
return SWELLAppMain(SWELLAPP_SHOULDDESTROY,0,0) > 0 ? NSTerminateLater : NSTerminateNow;
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
SWELLAppMain(SWELLAPP_DESTROY,0,0);
}
- (void)applicationDidBecomeActive:(NSNotification *)aNotification
{
if (!SWELLAppMain(SWELLAPP_ACTIVATE,TRUE,0))
SWELL_BroadcastMessage(WM_ACTIVATEAPP,TRUE,0);
}
- (void)applicationDidResignActive:(NSNotification *)aNotification
{
if (!SWELLAppMain(SWELLAPP_ACTIVATE,FALSE,0))
SWELL_BroadcastMessage(WM_ACTIVATEAPP,FALSE,0);
}
SWELL_APPAPI_DELEGATE_IMPL
SWELL_POSTMESSAGE_DELEGATE_IMPL
@end

View File

@@ -0,0 +1,7 @@
#include "swell.h"
int main()
{
MessageBox(NULL,"hello world","a",0);
return 0;
}

View File

@@ -0,0 +1,152 @@
#ifndef _SWELL_WINDOWS_H_
#define _SWELL_WINDOWS_H_
#ifdef _WIN32
#include <windows.h>
#else
#include "swell.h"
#define BIF_RETURNONLYFSDIRS 0x0001
#define BIF_DONTGOBELOWDOMAIN 0x0002
#define BIF_STATUSTEXT 0x0004
#define BIF_RETURNFSANCESTORS 0x0008
#define BIF_EDITBOX 0x0010
#define BIF_VALIDATE 0x0020
#define BIF_BROWSEFORCOMPUTER 0x1000
#define BIF_BROWSEFORPRINTER 0x2000
#define BIF_BROWSEINCLUDEFILES 0x4000
#define BFFM_INITIALIZED 1
#define BFFM_SELCHANGED 2
typedef int (CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
typedef struct __ITEMIDLIST ITEMIDLIST;
typedef const ITEMIDLIST *LPCITEMIDLIST;
typedef struct _browseinfoA {
HWND hwndOwner;
LPCITEMIDLIST pidlRoot;
LPSTR pszDisplayName;
LPCSTR lpszTitle;
UINT ulFlags;
BFFCALLBACK lpfn;
LPARAM lParam;
int iImage;
} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO;
#ifdef __cplusplus
class IMalloc
{
public:
void Release() { delete this; }
void Free(void *p) { free(p); }
};
#define SHGetMalloc(x) { *(x) = new IMalloc; }
#define SHGetPathFromIDList(src,dest) { if (src) {lstrcpyn(dest,(char *)src,MAX_PATH); } else *dest=0; }
#endif
#define BFFM_SETSELECTION (WM_USER + 102)
#define Shell_NotifyIcon(a,b) (0)
#define PostQuitMessage(x) { /* todo: mac quit message*/ }
#define SetClassLong(a,b,c) (0)
#define LoadIcon(a,b) ((HICON)0)
#define IsIconic(x) (0)
#define IsWindowEnabled(x) (1)
#define TrackPopupMenuEx(a,b,c,d,e,f) TrackPopupMenu(a,b,c,d,0,e,NULL)
#endif
typedef UINT (CALLBACK *LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM);
typedef struct tagOFNA {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCSTR lpstrFilter;
LPSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPSTR lpstrFile;
DWORD nMaxFile;
LPSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCSTR lpstrInitialDir;
LPCSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCSTR lpTemplateName;
} OPENFILENAME, *LPOPENFILENAME;
#define OFN_READONLY 0x00000001
#define OFN_OVERWRITEPROMPT 0x00000002
#define OFN_HIDEREADONLY 0x00000004
#define OFN_NOCHANGEDIR 0x00000008
#define OFN_SHOWHELP 0x00000010
#define OFN_ENABLEHOOK 0x00000020
#define OFN_ENABLETEMPLATE 0x00000040
#define OFN_ENABLETEMPLATEHANDLE 0x00000080
#define OFN_NOVALIDATE 0x00000100
#define OFN_ALLOWMULTISELECT 0x00000200
#define OFN_EXTENSIONDIFFERENT 0x00000400
#define OFN_PATHMUSTEXIST 0x00000800
#define OFN_FILEMUSTEXIST 0x00001000
#define OFN_CREATEPROMPT 0x00002000
#define OFN_SHAREAWARE 0x00004000
#define OFN_NOREADONLYRETURN 0x00008000
#define OFN_NOTESTFILECREATE 0x00010000
#define OFN_NONETWORKBUTTON 0x00020000
#define OFN_NOLONGNAMES 0x00040000
#define OFN_EXPLORER 0x00080000
#define OFN_NODEREFERENCELINKS 0x00100000
#define OFN_LONGNAMES 0x00200000
#define OFN_ENABLEINCLUDENOTIFY 0x00400000
#define OFN_ENABLESIZING 0x00800000
#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L
typedef struct _SHELLEXECUTEINFOA
{
DWORD cbSize;
ULONG fMask;
HWND hwnd;
LPCSTR lpVerb;
LPCSTR lpFile;
LPCSTR lpParameters;
LPCSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
#define InitCommonControls() { }
#define CoInitialize(x) { }
/*
#define IsDialogMessage(wnd,a) (0)
#define TranslateMessage(a) { }
#define DispatchMessage(a) { }
*/
#define INVALID_HANDLE_VALUE ((HANDLE)((unsigned int)-1))
#define RemoveDirectory(x) (!rmdir(x))
#define CharNext(x) ((x)+1)
#define CharPrev(base,x) ( (x)>(base)?(x)-1:(base))
#define isspace(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n')
#define lstrcpyA strcpy
#define lstrcpynA lstrcpyn
#endif