Add support for newer FontForge fields; Map undefined codepoint to 0xFFFD.
[SquirrelJME.git] / nanocoat / lib / scritchui / win32 / win32Window.c
blobbef507609788f750139fa52cb6074f88f676278e
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include "lib/scritchui/scritchuiTypes.h"
11 #include "lib/scritchui/win32/win32.h"
12 #include "lib/scritchui/win32/win32Intern.h"
14 sjme_errorCode sjme_scritchui_win32_windowContentMinimumSize(
15 sjme_attrInNotNull sjme_scritchui inState,
16 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow,
17 sjme_attrInPositiveNonZero sjme_jint width,
18 sjme_attrInPositiveNonZero sjme_jint height)
20 HWND window;
21 WINDOWPLACEMENT placement;
22 RECT winRect;
23 POINT clientPoint;
24 sjme_scritchui_dim* overhead;
25 sjme_jboolean notReady;
27 if (inState == NULL || inWindow == NULL)
28 return SJME_ERROR_NULL_ARGUMENTS;
30 /* Recover window. */
31 window = inWindow->component.common.handle[SJME_SUI_WIN32_H_HWND];
33 /* Calculate the overhead of the window, we need to do this with knowing */
34 /* the client rectangle and the window rectangle as GetSystemMetrics */
35 /* returns old information for compatibility purposes, which breaks */
36 /* on HiDPI or Vista Glass. */
37 overhead = &inWindow->minOverhead;
38 memset(&winRect, 0, sizeof(winRect));
39 memset(&clientPoint, 0, sizeof(clientPoint));
41 /* If either of these fail, the window exists but is not on the screen */
42 /* so any attempts to place it will fail. */
43 notReady = SJME_JNI_FALSE;
44 if (0 == GetWindowRect(window, &winRect))
45 notReady = SJME_JNI_TRUE;
46 if (0 == ClientToScreen(window, &clientPoint))
47 notReady = SJME_JNI_TRUE;
49 /* Do nothing yet if this is the case. */
50 if (notReady)
51 return SJME_ERROR_NONE;
53 /* The X coordinates are effectively a lie. */
54 overhead->width = (clientPoint.x - winRect.left) +
55 (GetSystemMetrics(SM_CXSIZEFRAME) * 2) +
56 (GetSystemMetrics(SM_CXEDGE) * 2);
58 /* This is correct. */
59 overhead->height = (clientPoint.y - winRect.top) +
60 GetSystemMetrics(SM_CYSIZEFRAME) +
61 GetSystemMetrics(SM_CYEDGE);
63 /* Add menu bar height? */
64 if (inWindow->menuBar != NULL)
65 overhead->height += GetSystemMetrics(SM_CYMENU);
67 /* Setup new placement information. */
68 memset(&placement, 0, sizeof(placement));
69 placement.length = sizeof(placement);
70 placement.flags = WPF_SETMINPOSITION;
71 placement.ptMinPosition.x = width + overhead->width;
72 placement.ptMinPosition.y = height + overhead->height;
74 /* Set the window placement. */
75 SetLastError(0);
76 if (0 == SetWindowPlacement(window, &placement))
77 return inState->implIntern->getLastError(inState,
78 SJME_ERROR_NATIVE_WIDGET_FAILURE);
80 /* Success? */
81 return inState->implIntern->getLastError(inState, SJME_ERROR_NONE);
84 sjme_errorCode sjme_scritchui_win32_windowNew(
85 sjme_attrInNotNull sjme_scritchui inState,
86 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow,
87 sjme_attrInNullable sjme_pointer ignored)
89 HWND window;
90 WNDCLASSEX windowClass;
91 ATOM classAtom;
93 if (inState == NULL || inWindow == NULL)
94 return SJME_ERROR_NULL_ARGUMENTS;
96 /* Register window class for this window. */
97 memset(&windowClass, 0, sizeof(windowClass));
98 windowClass.cbSize = sizeof(windowClass);
99 windowClass.hInstance = GetModuleHandle(NULL);
100 windowClass.lpszClassName = inWindow->component.strId;
101 windowClass.lpfnWndProc = inState->implIntern->windowProcWin32;
102 SetLastError(0);
103 classAtom = RegisterClassEx(&windowClass);
104 if (classAtom == 0)
105 return inState->implIntern->getLastError(inState,
106 SJME_ERROR_NATIVE_WIDGET_FAILURE);
108 /* Create new window. */
109 SetLastError(0);
110 window = CreateWindowEx(
111 WS_EX_APPWINDOW | WS_EX_CONTROLPARENT |
112 WS_EX_OVERLAPPEDWINDOW,
113 inWindow->component.strId,
114 "SquirrelJME",
115 WS_OVERLAPPEDWINDOW,
116 CW_USEDEFAULT, CW_USEDEFAULT,
117 CW_USEDEFAULT, CW_USEDEFAULT,
118 NULL,
119 NULL,
120 GetModuleHandle(NULL),
121 NULL);
122 if (window == NULL)
123 return inState->implIntern->getLastError(inState,
124 SJME_ERROR_NATIVE_WIDGET_CREATE_FAILED);
126 /* Store handle. */
127 inWindow->component.common.handle[SJME_SUI_WIN32_H_HWND] = window;
128 inWindow->component.common.handle[SJME_SUI_WIN32_H_HWNDATOM] =
129 (sjme_scritchui_handle)classAtom;
131 /* Link back to this window. */
132 SetLastError(0);
133 SetWindowLongPtr(window, GWLP_USERDATA,
134 (LONG_PTR)inWindow);
136 /* Success? */
137 return inState->implIntern->getLastError(inState, SJME_ERROR_NONE);
140 sjme_errorCode sjme_scritchui_win32_windowSetMenuBar(
141 sjme_attrInNotNull sjme_scritchui inState,
142 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow,
143 sjme_attrInNullable sjme_scritchui_uiMenuBar inMenuBar)
145 HWND window;
146 HMENU menu;
148 if (inState == NULL || inWindow == NULL)
149 return SJME_ERROR_NULL_ARGUMENTS;
151 /* Recover window and menu. */
152 window = inWindow->component.common.handle[SJME_SUI_WIN32_H_HWND];
153 menu = (inMenuBar == NULL ? NULL :
154 inMenuBar->menuKind.common.handle[SJME_SUI_WIN32_H_HMENU]);
156 /* Set the new menu. */
157 SetLastError(0);
158 if (0 == SetMenu(window, menu))
159 return inState->implIntern->getLastError(inState,
160 SJME_ERROR_NATIVE_WIDGET_FAILURE);
162 /* Success? */
163 return inState->implIntern->getLastError(inState, SJME_ERROR_NONE);
166 sjme_errorCode sjme_scritchui_win32_windowSetVisible(
167 sjme_attrInNotNull sjme_scritchui inState,
168 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow,
169 sjme_attrInValue sjme_jboolean isVisible)
171 HWND window;
173 if (inState == NULL || inWindow == NULL)
174 return SJME_ERROR_NULL_ARGUMENTS;
176 /* Recover window. */
177 window = inWindow->component.common.handle[SJME_SUI_WIN32_H_HWND];
179 /* Change visibility. */
180 SetLastError(0);
181 ShowWindow(window, (isVisible ? SW_SHOW : SW_HIDE));
183 /* Success? */
184 return inState->implIntern->getLastError(inState, SJME_ERROR_NONE);