Removed or moved a bunch of stale files from the old source. All that's left now is to re-add the main controls and recreate the test program.

This commit is contained in:
Pietro Gagliardi 2015-04-29 10:20:25 -04:00
parent 1288624725
commit 4c280ca42c
17 changed files with 0 additions and 864 deletions

View File

@ -1,20 +0,0 @@
OSMFILES = \
alloc.m \
button.m \
checkbox.m \
entry.m \
init.m \
label.m \
main.m \
menu.m \
newcontrol.m \
parent.m \
tab.m \
text.m \
util.m \
window.m
xCFLAGS += -mmacosx-version-min=10.7 -DMACOSX_DEPLOYMENT_TARGET=10.7
xLDFLAGS += -mmacosx-version-min=10.7 -lobjc -framework Foundation -framework AppKit
OUT = $(OUTBASE)

View File

@ -1,70 +0,0 @@
// 6 april 2015
#import "uipriv_darwin.h"
@interface uiApplication : NSApplication
@end
@implementation uiApplication
// hey look! we're overriding terminate:!
// we're going to make sure we can go back to main() whether Cocoa likes it or not!
// and just how are we going to do that, hm?
// (note: this is called after applicationShouldTerminate:)
- (void)terminate:(id)sender
{
// yes that's right folks: DO ABSOLUTELY NOTHING.
// the magic is [NSApp run] will just... stop.
// for debugging
NSLog(@"in terminate:");
}
@end
@interface uiAppDelegate : NSObject <NSApplicationDelegate>
@end
@implementation uiAppDelegate
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
{
// for debugging
NSLog(@"in applicationShouldTerminate:");
return NSTerminateNow;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
{
return NO;
}
@end
// we are not in control of the actual lifetimes and refcounts of NSViews (see http://stackoverflow.com/a/29523141/3408572)
// when we're done with a view, it'll be added as a subview of this one, and this one will be released on application shutdown
// we need this separate view because it's possible for controls to have no parent but still be alive
NSView *destroyedControlsView;
uiInitOptions options;
const char *uiInit(uiInitOptions *o)
{
options = *o;
[uiApplication sharedApplication];
// don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy!
// see https://github.com/andlabs/ui/issues/6
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp setDelegate:[uiAppDelegate new]];
// always do this so we always have an application menu
[NSApp setMainMenu:makeMenubar()];
// we can use a stock NSView for this
destroyedControlsView = [[NSView alloc] initWithFrame:NSZeroRect];
return NULL;
}
void uiFreeInitError(const char *err)
{
}

View File

@ -1,27 +0,0 @@
// 6 april 2015
#import "uipriv_darwin.h"
// #qo LDFLAGS: -lobjc -framework Foundation -framework AppKit
void uiMain(void)
{
[NSApp run];
}
void uiQuit(void)
{
NSEvent *e;
[NSApp stop:NSApp];
// stop: won't register until another event has passed; let's synthesize one
e = [NSEvent otherEventWithType:NSApplicationDefined
location:NSZeroPoint
modifierFlags:0
timestamp:[[NSProcessInfo processInfo] systemUptime]
windowNumber:0
context:[NSGraphicsContext currentContext]
subtype:0
data1:0
data2:0];
[NSApp postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO)
}

View File

@ -1,84 +0,0 @@
// 20 april 2015
#import "uipriv_darwin.h"
struct menuConfig {
BOOL hasQuit;
BOOL hasPreferences;
BOOL hasAbout;
};
static NSMenuItem *quitItem;
static NSMenuItem *preferencesItem;
static NSMenuItem *aboutItem;
void appendMenuItem(NSMenu *menu, const uiMenuItem *item, struct menuConfig *menuConfig)
{
NSMenuItem *mitem;
switch (item->Type) {
case uiMenuItemTypeCommand:
case uiMenuItemTypeCheckbox:
mitem = [[NSMenuItem alloc] initWithTitle:toNSString(item->Name) action:NULL keyEquivalent:@""];
[menu addItem:mitem];
return;
case uiMenuItemTypeQuit:
// TODO verify name
menuConfig->hasQuit = YES;
return;
case uiMenuItemTypePreferences:
// TODO verify name
menuConfig->hasPreferences = YES;
return;
case uiMenuItemTypeAbout:
// TODO verify name
menuConfig->hasAbout = YES;
return;
case uiMenuItemTypeSeparator:
// TODO verify name
[menu addItem:[NSMenuItem separatorItem]];
return;
}
// TODO complain
}
NSMenuItem *makeMenu(const char *name, const uiMenuItem *items, struct menuConfig *menuConfig)
{
NSMenuItem *menubarItem;
NSMenu *menu;
const uiMenuItem *i;
menubarItem = [[NSMenuItem alloc] initWithTitle:toNSString(name) action:NULL keyEquivalent:@""];
menu = [[NSMenu alloc] initWithTitle:toNSString(name)];
for (i = items; i->Type != 0; i++)
appendMenuItem(menu, i, menuConfig);
[menubarItem setSubmenu:menu];
return menubarItem;
}
NSMenu *makeMenubar(void)
{
NSMenu *menubar;
struct menuConfig menuConfig;
const uiMenu *m;
menubar = [[NSMenu alloc] initWithTitle:@""];
// always build the application menu
buildApplicationMenu(menubar);
memset(&menuConfig, 0, sizeof (struct menuConfig));
if (options.Menu != NULL)
for (m = options.Menu; m->Name != NULL; m++)
[menubar addItem:makeMenu(m->Name, m->Items, &menuConfig)];
if (menuConfig.hasQuit)
[quitItem setEnabled:YES];
if (menuConfig.hasPreferences)
[preferencesItem setEnabled:YES];
if (menuConfig.hasAbout)
[aboutItem setEnabled:YES];
return menubar;
}

View File

@ -1,134 +0,0 @@
// 17 april 2015
#import "uipriv_darwin.h"
@interface uipParent : NSView {
uiControl *mainControl;
intmax_t marginLeft;
intmax_t marginTop;
intmax_t marginRight;
intmax_t marginBottom;
}
- (void)uipDestroyMainControl;
- (void)uipSetMainControl:(uiControl *)mainControl parent:(uiParent *)p;
- (void)uipSetMarginLeft:(intmax_t)left top:(intmax_t)top right:(intmax_t)right bottom:(intmax_t)bottom;
- (void)uipUpdate;
@end
@implementation uipParent
uiLogObjCClassAllocations
- (void)setFrameSize:(NSSize)s
{
[super setFrameSize:s];
[self uipUpdate];
}
- (void)uipDestroyMainControl
{
if (self->mainControl != NULL) {
// we have to do this before we can destroy controls
uiControlSetParent(self->mainControl, NULL);
uiControlDestroy(self->mainControl);
self->mainControl = NULL;
}
}
- (void)uipSetMainControl:(uiControl *)mainControl parent:(uiParent *)p
{
if (self->mainControl != NULL)
uiControlSetParent(self->mainControl, NULL);
self->mainControl = mainControl;
if (self->mainControl != NULL)
uiControlSetParent(self->mainControl, p);
}
- (void)uipSetMarginLeft:(intmax_t)left top:(intmax_t)top right:(intmax_t)right bottom:(intmax_t)bottom
{
self->marginLeft = left;
self->marginTop = top;
self->marginRight = right;
self->marginBottom = bottom;
}
// These are based on measurements from Interface Builder.
// These seem to be based on Auto Layout constants, but I don't see an API that exposes these...
// This one is 8 for most pairs of controls that I've tried; the only difference is between two pushbuttons, where it's 12...
#define macXPadding 8
// Likewise, this one appears to be 12 for pairs of push buttons...
#define macYPadding 8
- (void)uipUpdate
{
uiSizing d;
intmax_t x, y, width, height;
if (self->mainControl == NULL)
return;
x = [self bounds].origin.x + self->marginLeft;
y = [self bounds].origin.y + self->marginTop;
width = [self bounds].size.width - (self->marginLeft + self->marginRight);
height = [self bounds].size.height - (self->marginTop + self->marginBottom);
d.xPadding = macXPadding;
d.yPadding = macYPadding;
uiControlResize(self->mainControl, x, y, width, height, &d);
}
@end
static void parentDestroy(uiParent *pp)
{
uipParent *p = (uipParent *) (pp->Internal);
[p retain]; // to avoid destruction upon removing from superview
[p uipDestroyMainControl];
[p removeFromSuperview];
[destroyedControlsView addSubview:p];
[p release];
}
static uintptr_t parentHandle(uiParent *p)
{
return (uintptr_t) (p->Internal);
}
static void parentSetMainControl(uiParent *pp, uiControl *mainControl)
{
uipParent *p = (uipParent *) (pp->Internal);
[p uipSetMainControl:mainControl parent:pp];
}
static void parentSetMargins(uiParent *pp, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom)
{
uipParent *p = (uipParent *) (pp->Internal);
[p uipSetMarginLeft:left top:top right:right bottom:bottom];
}
static void parentUpdate(uiParent *pp)
{
uipParent *p = (uipParent *) (pp->Internal);
[p uipUpdate];
}
uiParent *uiNewParent(uintptr_t osParent)
{
uiParent *p;
uipParent *pp;
p = uiNew(uiParent);
pp = [[uipParent alloc] initWithFrame:NSZeroRect];
// don't use osParent; we'll need to call specific selectors to set the parent view
p->Internal = pp;
p->Destroy = parentDestroy;
p->Handle = parentHandle;
p->SetMainControl = parentSetMainControl;
p->SetMargins = parentSetMargins;
p->Update = parentUpdate;
return p;
}

View File

@ -1,46 +0,0 @@
// 6 january 2015
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_7
#import <Cocoa/Cocoa.h>
#import "../uipriv.h"
#import "../ui_darwin.h"
#define toNSString(str) [NSString stringWithUTF8String:(str)]
#define fromNSString(str) [(str) UTF8String]
#define uiLogObjCClassAllocations \
+ (id)alloc \
{ \
id thing; \
thing = [super alloc]; \
if (options.debugLogAllocations) \
fprintf(stderr, "%p alloc %s\n", thing, [[self className] UTF8String]); \
return thing; \
} \
- (void)dealloc \
{ \
[super dealloc]; \
if (options.debugLogAllocations) \
fprintf(stderr, "%p free\n", self); \
}
#define VIEW(c) uiControlHandle(uiControl(c))
// init.m
extern NSView *destroyedControlsView;
// util.m
extern void setStandardControlFont(NSControl *);
extern void disableAutocorrect(NSTextView *);
// parent.m
// These are based on measurements from Interface Builder.
// These seem to be based on Auto Layout constants, but I don't see an API that exposes these...
#define macXMargin 20
#define macYMargin 20
// entry.m
extern void finishNewTextField(NSTextField *, BOOL);
// menu.m
extern NSMenu *makeMenubar(void);

View File

@ -1,23 +0,0 @@
// 7 april 2015
/*
This file assumes that you have imported <Cocoa/Cocoa.h> and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls on Mac OS X.
*/
#ifndef __UI_UI_DARWIN_H__
#define __UI_UI_DARWIN_H__
// uiDarwinNewControl() initializes the given uiControl with the given Cocoa control inside.
// The second parameter should come from [RealControlType class].
// The two scrollView parameters allow placing scrollbars on the new control.
// The two onDestroy parameters define a function and its parameter to call when the widget is destroyed.
extern void uiDarwinNewControl(uiControl *c, Class class, BOOL inScrollView, BOOL scrollViewHasBorder, void (*onDestroy)(void *), void *onDestroyData);
// You can use this function from within your control implementations to return text strings that can be freed with uiTextFree().
extern char *uiDarwinNSStringToText(NSString *);
struct uiSizingSys {
// this structure currently left blank
};
#endif

View File

@ -1,21 +0,0 @@
// 7 april 2015
/*
This file assumes that you have included <gtk/gtk.h> and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls on Unix systems that use GTK+ to provide their UI (currently all except Mac OS X).
*/
#ifndef __UI_UI_UNIX_H__
#define __UI_UI_UNIX_H__
// uiUnixNewControl() creates a new uiControl with the given GTK+ control inside, storing it in the uiControl at c.
// The second parameter is the type of the control, as passed to the first argument of g_object_new().
// The two scrolledWindow parameters allow placing scrollbars on the new control.
// The destroy parameters are for a function that should be called when destroying the widget.
// The firstProperty parameter and beyond allow passing construct properties to the new control, as with g_object_new(); end this list with NULL.
extern void uiUnixNewControl(uiControl *c, GType type, gboolean inScrolledWindow, gboolean scrolledWindowHasBorder, void (*destroy)(void *), void *onDestroyData, const char *firstProperty, ...);
struct uiSizingSys {
// this structure currently left blank
};
#endif

View File

@ -1,58 +0,0 @@
// 7 april 2015
/*
This file assumes that you have included <windows.h> and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls in Windows.
*/
#ifndef __UI_UI_WINDOWS_H__
#define __UI_UI_WINDOWS_H__
// uiWindowsNewControl() initializes the given uiControl with the given Windows API control inside.
// You will need to provide the preferredSize() method yourself.
typedef struct uiWindowsNewControlParams uiWindowsNewControlParams;
struct uiWindowsNewControlParams {
// These match the CreateWindowExW() function.
DWORD dwExStyle;
LPCWSTR lpClassName;
LPCWSTR lpWindowName;
DWORD dwStyle; // WS_CHILD and WS_VISIBLE are automatically applied.
HINSTANCE hInstance;
// Set this to non-FALSE to use the standard control font used by other ui controls.
BOOL useStandardControlFont;
// These are called when the control sends a WM_COMMAND or WM_NOTIFY (respectively) to its parent.
// ui redirects the message back and calls these functions.
// Store the result in *lResult and return any non-FALSE value (such as TRUE) to return the given result; return FALSE to pass the notification up to your window procedure.
// Note that these are only issued if they come from the uiControl itself; notifications from children of the uiControl (such as a header control) will be received normally.
BOOL (*onWM_COMMAND)(uiControl *c, WORD code, LRESULT *lResult);
// TODO set idFrom to 0?
BOOL (*onWM_NOTIFY)(uiControl *c, NMHDR *nm, LRESULT *lResult);
// This is called when the widget is ready to be destroyed.
void (*onDestroy)(void *data);
void *onDestroyData;
};
void uiWindowsNewControl(uiControl *c, uiWindowsNewControlParams *p);
// This contains the Windows-specific parts of the uiSizing structure.
// baseX and baseY are the dialog base units.
// internalLeading is the standard control font's internal leading; labels in uiForms use this for correct Y positioning.
struct uiSizingSys {
int baseX;
int baseY;
LONG internalLeading;
};
// Use these in your preferredSize() implementation with baseX and baseY.
#define uiDlgUnitsToX(dlg, baseX) MulDiv((dlg), baseX, 4)
#define uiDlgUnitsToY(dlg, baseY) MulDiv((dlg), baseY, 8)
// and use this if you need the text of the window width
extern intmax_t uiWindowsWindowTextWidth(HWND hwnd);
// these functions get and set the window text for such a uiControl
// the value returned should be freed with uiFreeText()
extern char *uiWindowsControlText(uiControl *);
extern void uiWindowsControlSetText(uiControl *, const char *);
#endif

View File

@ -1,12 +0,0 @@
// 6 april 2015
#include <stdlib.h>
#include "ui.h"
extern uiInitOptions options;
extern void *uiAlloc(size_t, const char *);
#define uiNew(T) ((T *) uiAlloc(sizeof (T), #T ))
extern void *uiRealloc(void *, size_t, const char *);
extern void uiFree(void *);
extern void complain(const char *, ...);

View File

@ -1,21 +0,0 @@
OSCFILES = \
alloc.c \
button.c \
checkbox.c \
entry.c \
init.c \
label.c \
lifetimes.c \
main.c \
menu.c \
newcontrol.c \
parent.c \
tab.c \
text.c \
util.c \
window.c
xCFLAGS += `pkg-config --cflags gtk+-3.0`
xLDFLAGS += `pkg-config --libs gtk+-3.0`
OUT = $(OUTBASE)

View File

@ -1,21 +0,0 @@
// 6 april 2015
#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_32
#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_32
#define GDK_VERSION_MIN_REQUIRED GDK_VERSION_3_4
#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_4
#include <gtk/gtk.h>
#include "../uipriv.h"
#include "../ui_unix.h"
#define gtkXMargin 12
#define gtkYMargin 12
#define widget(c) uiControlHandle(uiControl(c))
#define WIDGET(c) GTK_WIDGET(widget(c))
// lifetimes.c
extern gulong blockDestruction(GtkWidget *, void *);
extern void readyToDestroy(GtkWidget *, gulong);
// menu.c
extern GtkWidget *makeMenubar(void);

View File

@ -1,34 +0,0 @@
OSCFILES = \
alloc.c \
button.c \
checkbox.c \
comctl32.c \
debug.c \
entry.c \
init.c \
label.c \
main.c \
menu.c \
newcontrol.c \
parent.c \
tab.c \
text.c \
util.c \
window.c
xLDFLAGS += \
-luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32 -lcomdlg32 -lole32 -loleaut32 -loleacc -luuid
OUT = $(OUTBASE).exe
ifeq ($(ARCH),64)
CC = x86_64-w64-mingw32-gcc
RC = x86_64-w64-mingw32-windres
xCFLAGS += -m64
xLDFLAGS += -m64
else
CC = i686-w64-mingw32-gcc
RC = i686-w64-mingw32-windres
xCFLAGS += -m32
xLDFLAGS += -m32
endif

View File

@ -1,105 +0,0 @@
// 17 july 2014
#include "uipriv_windows.h"
static ULONG_PTR comctlManifestCookie;
static HMODULE comctl32;
// these are listed as WINAPI in both Microsoft's and MinGW's headers, but not on MSDN for some reason
BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
#define wantedICCClasses ( \
ICC_STANDARD_CLASSES | /* user32.dll controls */ \
ICC_PROGRESS_CLASS | /* progress bars */ \
ICC_TAB_CLASSES | /* tabs */ \
ICC_LISTVIEW_CLASSES | /* table headers */ \
ICC_UPDOWN_CLASS | /* spinboxes */ \
0)
// note that this is an 8-bit character string we're writing; see the encoding clause
static const char manifest[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n version=\"1.0.0.0\"\n processorArchitecture=\"*\"\n name=\"CompanyName.ProductName.YourApplication\"\n type=\"win32\"\n/>\n<description>Your application description here.</description>\n<dependency>\n <dependentAssembly>\n <assemblyIdentity\n type=\"win32\"\n name=\"Microsoft.Windows.Common-Controls\"\n version=\"6.0.0.0\"\n processorArchitecture=\"*\"\n publicKeyToken=\"6595b64144ccf1df\"\n language=\"*\"\n />\n </dependentAssembly>\n</dependency>\n</assembly>\n";
/*
Windows requires a manifest file to enable Common Controls version 6.
The only way to not require an external manifest is to synthesize the manifest ourselves.
We can use the activation context API to load it at runtime.
References:
- http://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest
- http://support.microsoft.com/kb/830033
Because neither Go nor MinGW have ways to compile in resources like this (as far as I know), we have to do the work ourselves.
*/
const char *initCommonControls(void)
{
WCHAR temppath[MAX_PATH + 1];
WCHAR filename[MAX_PATH + 1];
HANDLE file;
DWORD nExpected, nGot;
ACTCTX actctx;
HANDLE ac;
INITCOMMONCONTROLSEX icc;
FARPROC f;
// this is listed as WINAPI in both Microsoft's and MinGW's headers, but not on MSDN for some reason
BOOL (*WINAPI ficc)(const LPINITCOMMONCONTROLSEX);
if (GetTempPathW(MAX_PATH + 1, temppath) == 0)
return "getting temporary path for writing manifest file in initCommonControls()";
if (GetTempFileNameW(temppath, L"manifest", 0, filename) == 0)
return "getting temporary filename for writing manifest file in initCommonControls()";
file = CreateFileW(filename, GENERIC_WRITE,
0, // don't share while writing
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == NULL)
return "creating manifest file in initCommonControls()";
nExpected = (sizeof manifest / sizeof manifest[0]) - 1; // - 1 to omit the terminating null character)
SetLastError(0); // catch errorless short writes
if (WriteFile(file, manifest, nExpected, &nGot, NULL) == 0)
return "writing manifest file in initCommonControls()";
if (nGot != nExpected) {
DWORD lasterr;
lasterr = GetLastError();
if (lasterr == 0)
return "writing entire manifest file (short write) without error code in initCommonControls()";
return "writing entire manifest file (short write) in initCommonControls()";
}
if (CloseHandle(file) == 0)
return "closing manifest file (this IS an error here because not doing so will prevent Windows from being able to use the manifest file in an activation context) in initCommonControls()";
ZeroMemory(&actctx, sizeof (ACTCTX));
actctx.cbSize = sizeof (ACTCTX);
actctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT;
actctx.lpSource = filename;
ac = CreateActCtx(&actctx);
if (ac == INVALID_HANDLE_VALUE)
return "creating activation context for synthesized manifest file in initCommonControls()";
if (ActivateActCtx(ac, &comctlManifestCookie) == FALSE)
return "activating activation context for synthesized manifest file in initCommonControls()";
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
icc.dwICC = wantedICCClasses;
comctl32 = LoadLibraryW(L"comctl32.dll");
if (comctl32 == NULL)
return "loading comctl32.dll in initCommonControls()";
// GetProcAddress() only takes a multibyte string
#define LOAD(fn) f = GetProcAddress(comctl32, fn); \
if (f == NULL) \
return "loading " fn "() in initCommonControls()";
LOAD("InitCommonControlsEx");
ficc = (BOOL (*WINAPI)(const LPINITCOMMONCONTROLSEX)) f;
LOAD("SetWindowSubclass");
fv_SetWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR)) f;
LOAD("RemoveWindowSubclass");
fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
LOAD("DefSubclassProc");
fv_DefSubclassProc = (LRESULT (*WINAPI)(HWND, UINT, WPARAM, LPARAM)) f;
if ((*ficc)(&icc) == FALSE)
return "initializing Common Controls (comctl32.dll) in initCommonControls()";
return NULL;
}

View File

@ -1,111 +0,0 @@
// 25 february 2015
#include "uipriv_windows.h"
// uncomment the following line to enable debug messages
#define tableDebug
// uncomment the following line to halt on a debug message
#define tableDebugStop
#ifdef tableDebug
#include <stdio.h>
HRESULT logLastError(const char *context)
{
DWORD le;
WCHAR *msg;
BOOL parenthesize = FALSE;
BOOL localFreeFailed = FALSE;
DWORD localFreeLastError;
le = GetLastError();
fprintf(stderr, "%s: ", context);
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, le, 0, (LPWSTR) (&msg), 0, NULL) != 0) {
fprintf(stderr, "%S (", msg);
if (LocalFree(msg) != NULL) {
localFreeFailed = TRUE;
localFreeLastError = GetLastError();
}
parenthesize = TRUE;
}
fprintf(stderr, "GetLastError() == %I32u", le);
if (parenthesize)
fprintf(stderr, ")");
if (localFreeFailed)
fprintf(stderr, "; local free of system message failed with last error %I32u", localFreeLastError);
fprintf(stderr, "\n");
#ifdef tableDebugStop
DebugBreak();
#endif
SetLastError(le);
// a function does not have to set a last error
// if the last error we get is actually 0, then HRESULT_FROM_WIN32(0) will return S_OK (0 cast to an HRESULT, since 0 <= 0), which we don't want
// prevent this by returning E_FAIL, so the rest of the Table code doesn't barge onward
if (le == 0)
return E_FAIL;
return HRESULT_FROM_WIN32(le);
}
HRESULT logHRESULT(const char *context, HRESULT hr)
{
WCHAR *msg;
BOOL parenthesize = FALSE;
BOOL localFreeFailed = FALSE;
DWORD localFreeLastError;
fprintf(stderr, "%s: ", context);
// this isn't technically documented, but everyone does it, including Microsoft (see the implementation of _com_error::ErrorMessage() in a copy of comdef.h that comes with the Windows DDK)
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) hr, 0, (LPWSTR) (&msg), 0, NULL) != 0) {
fprintf(stderr, "%S (", msg);
if (LocalFree(msg) != NULL) {
localFreeFailed = TRUE;
localFreeLastError = GetLastError();
}
parenthesize = TRUE;
}
fprintf(stderr, "HRESULT == 0x%I32X", hr);
if (parenthesize)
fprintf(stderr, ")");
if (localFreeFailed)
fprintf(stderr, "; local free of system message failed with last error %I32u", localFreeLastError);
fprintf(stderr, "\n");
#ifdef tableDebugStop
DebugBreak();
#endif
return hr;
}
HRESULT logMemoryExhausted(const char *reason)
{
fprintf(stderr, "memory exhausted %s\n", reason);
#ifdef tableDebugStop
DebugBreak();
#endif
return E_OUTOFMEMORY;
}
#else
HRESULT logLastError(const char *reason)
{
DWORD le;
le = GetLastError();
// we shouldn't need to do this, but let's do this anyway just to be safe
SetLastError(le);
if (le == 0)
return E_FAIL;
return HRESULT_FROM_WIN32(le);
}
HRESULT logHRESULT(const char *reason, HRESULT hr)
{
return hr;
}
HRESULT logMemoryExhausted(const char *reason)
{
return E_OUTOFMEMORY;
}
#endif

View File

@ -1,77 +0,0 @@
// 6 january 2015
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#define CINTERFACE
#define COBJMACROS
// see https://github.com/golang/go/issues/9916#issuecomment-74812211
#define INITGUID
// get Windows version right; right now Windows XP
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
#include <windows.h>
#include <commctrl.h>
#include <stdint.h>
#include <uxtheme.h>
#include <string.h>
#include <wchar.h>
#include <windowsx.h>
#include <vsstyle.h>
#include <vssym32.h>
#include <stdarg.h>
#include <oleacc.h>
#include <stdio.h>
#include "../uipriv.h"
#include "../ui_windows.h"
// ui internal window messages
enum {
// redirected WM_COMMAND and WM_NOTIFY
msgCOMMAND = WM_APP + 0x40, // start offset just to be safe
msgNOTIFY,
msgUpdateChild, // fake because Windows seems to SWP_NOSIZE MoveWindow()s and SetWindowPos()s that don't change the window size (even if SWP_NOSIZE isn't specified)
msgCanDestroyNow,
};
#define HWND(c) ((HWND) uiControlHandle(uiControl(c)))
#define uiParentHWND(p) ((HWND) uiParentHandle(p))
// debug.c
extern HRESULT logLastError(const char *);
extern HRESULT logHRESULT(const char *, HRESULT);
extern HRESULT logMemoryExhausted(const char *);
// init.c
extern HINSTANCE hInstance;
extern int nCmdShow;
extern HFONT hMessageFont;
extern HBRUSH hollowBrush;
// util.c
extern int windowClassOf(HWND, ...);
// text.c
extern WCHAR *toUTF16(const char *);
extern char *toUTF8(const WCHAR *);
extern WCHAR *windowText(HWND);
// comctl32.c
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
extern const char *initCommonControls(void);
// window.c
extern ATOM registerWindowClass(HICON, HCURSOR);
// parent.c
extern HWND initialParent;
extern const char *initParent(HICON, HCURSOR);
// menu.c
extern HMENU makeMenubar(void);
extern const uiMenuItem *menuIDToItem(UINT_PTR);