1/*
2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#ifndef _AWT_H_
27#define _AWT_H_
28
29#ifndef _WIN32_WINNT
30#define _WIN32_WINNT 0x0600
31#endif
32
33#ifndef _WIN32_IE
34#define _WIN32_IE 0x0600
35#endif
36
37//#ifndef NTDDI_VERSION
38//#define NTDDI_VERSION NTDDI_LONGHORN
39//#endif
40
41#include "stdhdrs.h"
42#include "alloc.h"
43#include "awt_Debug.h"
44
45extern COLORREF DesktopColor2RGB(int colorIndex);
46
47class AwtObject;
48typedef AwtObject* PDATA;
49
50#define JNI_IS_TRUE(obj) ((obj) ? JNI_TRUE : JNI_FALSE)
51
52#define JNI_CHECK_NULL_GOTO(obj, msg, where) {                            \
53    if (obj == NULL) {                                                    \
54        env->ExceptionClear();                                            \
55        JNU_ThrowNullPointerException(env, msg);                          \
56        goto where;                                                       \
57    }                                                                     \
58}
59
60#define JNI_CHECK_PEER_GOTO(peer, where) {                                \
61    JNI_CHECK_NULL_GOTO(peer, "peer", where);                             \
62    pData = JNI_GET_PDATA(peer);                                          \
63    if (pData == NULL) {                                                  \
64        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
65        goto where;                                                       \
66    }                                                                     \
67}
68
69#define JNI_CHECK_NULL_RETURN(obj, msg) {                                 \
70    if (obj == NULL) {                                                    \
71        env->ExceptionClear();                                            \
72        JNU_ThrowNullPointerException(env, msg);                          \
73        return;                                                           \
74    }                                                                     \
75}
76
77#define JNI_CHECK_PEER_RETURN(peer) {                                     \
78    JNI_CHECK_NULL_RETURN(peer, "peer");                                  \
79    pData = JNI_GET_PDATA(peer);                                          \
80    if (pData == NULL) {                                                  \
81        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
82        return;                                                           \
83    }                                                                     \
84}
85
86#define JNI_CHECK_PEER_CREATION_RETURN(peer) {                            \
87    if (peer == NULL ) {                                                  \
88        return;                                                           \
89    }                                                                     \
90    pData = JNI_GET_PDATA(peer);                                          \
91    if (pData == NULL) {                                                  \
92        return;                                                           \
93    }                                                                     \
94}
95
96#define JNI_CHECK_NULL_RETURN_NULL(obj, msg) {                            \
97    if (obj == NULL) {                                                    \
98        env->ExceptionClear();                                            \
99        JNU_ThrowNullPointerException(env, msg);                          \
100        return 0;                                                         \
101    }                                                                     \
102}
103
104#define JNI_CHECK_NULL_RETURN_VAL(obj, msg, val) {                        \
105    if (obj == NULL) {                                                    \
106        env->ExceptionClear();                                            \
107        JNU_ThrowNullPointerException(env, msg);                          \
108        return val;                                                       \
109    }                                                                     \
110}
111
112#define JNI_CHECK_PEER_RETURN_NULL(peer) {                                \
113    JNI_CHECK_NULL_RETURN_NULL(peer, "peer");                             \
114    pData = JNI_GET_PDATA(peer);                                          \
115    if (pData == NULL) {                                                  \
116        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
117        return 0;                                                         \
118    }                                                                     \
119}
120
121#define JNI_CHECK_PEER_RETURN_VAL(peer, val) {                            \
122    JNI_CHECK_NULL_RETURN_VAL(peer, "peer", val);                         \
123    pData = JNI_GET_PDATA(peer);                                          \
124    if (pData == NULL) {                                                  \
125        THROW_NULL_PDATA_IF_NOT_DESTROYED(peer);                          \
126        return val;                                                       \
127    }                                                                     \
128}
129
130#define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) {                         \
131    jboolean destroyed = JNI_GET_DESTROYED(peer);                         \
132    if (destroyed != JNI_TRUE) {                                          \
133        env->ExceptionClear();                                            \
134        JNU_ThrowNullPointerException(env, "null pData");                 \
135    }                                                                     \
136}
137
138#define JNI_GET_PDATA(peer) (PDATA) env->GetLongField(peer, AwtObject::pDataID)
139#define JNI_GET_DESTROYED(peer) env->GetBooleanField(peer, AwtObject::destroyedID)
140
141#define JNI_SET_PDATA(peer, data) env->SetLongField(peer,                  \
142                                                    AwtObject::pDataID,    \
143                                                    (jlong)data)
144#define JNI_SET_DESTROYED(peer) env->SetBooleanField(peer,                   \
145                                                     AwtObject::destroyedID, \
146                                                     JNI_TRUE)
147/*  /NEW JNI */
148
149/*
150 * IS_WIN64 returns TRUE on 64-bit Itanium
151 */
152#if defined (_WIN64)
153    #define IS_WIN64 TRUE
154#else
155    #define IS_WIN64 FALSE
156#endif
157
158/*
159 * IS_WIN2000 returns TRUE on 2000, XP and Vista
160 * IS_WINXP returns TRUE on XP and Vista
161 * IS_WINVISTA returns TRUE on Vista
162 */
163#define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5)
164#define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5)
165#define IS_WINVISTA (LOBYTE(LOWORD(::GetVersion())) >= 6)
166
167#define IS_WINVER_ATLEAST(maj, min) \
168                   ((maj) < LOBYTE(LOWORD(::GetVersion())) || \
169                      (maj) == LOBYTE(LOWORD(::GetVersion())) && \
170                      (min) <= HIBYTE(LOWORD(::GetVersion())))
171
172/*
173 * macros to crack a LPARAM into two ints -- used for signed coordinates,
174 * such as with mouse messages.
175 */
176#define LO_INT(l)           ((int)(short)(l))
177#define HI_INT(l)           ((int)(short)(((DWORD)(l) >> 16) & 0xFFFF))
178
179extern JavaVM *jvm;
180
181// Platform encoding is Unicode (UTF-16), re-define JNU_ functions
182// to proper JNI functions.
183#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<const jchar*>(x), static_cast<jsize>(_tcslen(x)))
184#define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y))
185#define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y))
186
187/*
188 * Itanium symbols needed for 64-bit compilation.
189 * These are defined in winuser.h in the August 2001 MSDN update.
190 */
191#ifndef GCLP_HBRBACKGROUND
192    #ifdef _WIN64
193        #error Macros for GetClassLongPtr, etc. are for 32-bit windows only
194    #endif /* !_WIN64 */
195    #define GetClassLongPtr GetClassLong
196    #define SetClassLongPtr SetClassLong
197    #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
198    #define GCLP_HCURSOR GCL_HCURSOR
199    #define GCLP_HICON GCL_HICON
200    #define GCLP_HICONSM GCL_HICONSM
201    #define GCLP_HMODULE GCL_HMODULE
202    #define GCLP_MENUNAME GCL_MENUNAME
203    #define GCLP_WNDPROC GCL_WNDPROC
204    #define GetWindowLongPtr GetWindowLong
205    #define SetWindowLongPtr SetWindowLong
206    #define GWLP_WNDPROC GWL_WNDPROC
207    #define GWLP_HINSTANCE GWL_HINSTANCE
208    #define GWLP_HWNDPARENT GWL_HWNDPARENT
209    #define GWLP_ID GWL_ID
210    #define GWLP_USERDATA GWL_USERDATA
211    #define DWLP_DLGPROC DWL_DLGPROC
212    #define DWLP_MSGRESULT DWL_MSGRESULT
213    #define DWLP_USER DWL_USER
214#endif /* !GCLP_HBRBACKGROUND */
215
216/*
217 * macros for saving and restoring FPU control word
218 * NOTE: float.h must be defined if using these macros
219 */
220#define SAVE_CONTROLWORD  \
221  unsigned int fpu_cw = _control87(0, 0);
222
223#define RESTORE_CONTROLWORD  \
224  if (_control87(0, 0) != fpu_cw) {  \
225    _control87(fpu_cw, 0xffffffff);  \
226  }
227
228/*
229 * checks if the current thread is/isn't the toolkit thread
230 */
231#if defined(DEBUG)
232#define CHECK_IS_TOOLKIT_THREAD() \
233  if (GetCurrentThreadId() != AwtToolkit::MainThread())  \
234  { JNU_ThrowInternalError(env,"Operation is not permitted on non-toolkit thread!\n"); }
235#define CHECK_ISNOT_TOOLKIT_THREAD()  \
236  if (GetCurrentThreadId() == AwtToolkit::MainThread())  \
237  { JNU_ThrowInternalError(env,"Operation is not permitted on toolkit thread!\n"); }
238#else
239#define CHECK_IS_TOOLKIT_THREAD()
240#define CHECK_ISNOT_TOOLKIT_THREAD()
241#endif
242
243
244struct EnvHolder
245{
246    JavaVM *m_pVM;
247    JNIEnv *m_env;
248    bool    m_isOwner;
249    EnvHolder(
250        JavaVM *pVM,
251        LPCSTR name = "COM holder",
252        jint ver = JNI_VERSION_1_2)
253    : m_pVM(pVM),
254      m_env((JNIEnv *)JNU_GetEnv(pVM, ver)),
255      m_isOwner(false)
256    {
257        if (NULL == m_env) {
258            JavaVMAttachArgs attachArgs;
259            attachArgs.version  = ver;
260            attachArgs.name     = const_cast<char *>(name);
261            attachArgs.group    = NULL;
262            jint status = m_pVM->AttachCurrentThread(
263                (void**)&m_env,
264                &attachArgs);
265            m_isOwner = (NULL!=m_env);
266        }
267    }
268    ~EnvHolder() {
269        if (m_isOwner) {
270            m_pVM->DetachCurrentThread();
271        }
272    }
273    operator bool()  const { return NULL!=m_env; }
274    bool operator !()  const { return NULL==m_env; }
275    operator JNIEnv*() const { return m_env; }
276    JNIEnv* operator ->() const { return m_env; }
277};
278
279template <class T>
280class JLocalRef {
281    JNIEnv* m_env;
282    T m_localJRef;
283
284public:
285    JLocalRef(JNIEnv* env, T localJRef = NULL)
286    : m_env(env),
287    m_localJRef(localJRef)
288    {}
289    T Detach() {
290        T ret = m_localJRef;
291        m_localJRef = NULL;
292        return ret;
293    }
294    void Attach(T newValue) {
295        if (m_localJRef) {
296            m_env->DeleteLocalRef((jobject)m_localJRef);
297        }
298        m_localJRef = newValue;
299    }
300
301    operator T() { return m_localJRef; }
302    operator bool() { return NULL!=m_localJRef; }
303    bool operator !() { return NULL==m_localJRef; }
304
305    ~JLocalRef() {
306        if (m_localJRef) {
307            m_env->DeleteLocalRef((jobject)m_localJRef);
308        }
309    }
310};
311
312typedef JLocalRef<jobject> JLObject;
313typedef JLocalRef<jstring> JLString;
314typedef JLocalRef<jclass>  JLClass;
315
316/*
317 * Class to encapsulate the extraction of the java string contents
318 * into a buffer and the cleanup of the buffer
319 */
320class JavaStringBuffer
321{
322protected:
323    LPWSTR m_pStr;
324    jsize  m_dwSize;
325    LPWSTR getNonEmptyString() {
326        return (NULL==m_pStr)
327                ? L""
328                : m_pStr;
329    }
330
331public:
332    JavaStringBuffer(jsize cbTCharCount) {
333        m_dwSize = cbTCharCount;
334        m_pStr = (0 == m_dwSize)
335            ? NULL
336            : (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
337    }
338
339    JavaStringBuffer(JNIEnv *env, jstring text) {
340        m_dwSize = (NULL == text)
341            ? 0
342            : env->GetStringLength(text);
343        if (0 == m_dwSize) {
344            m_pStr = NULL;
345        } else {
346            m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (m_dwSize+1), sizeof(WCHAR) );
347            env->GetStringRegion(text, 0, m_dwSize, reinterpret_cast<jchar *>(m_pStr));
348            m_pStr[m_dwSize] = 0;
349        }
350    }
351
352
353    ~JavaStringBuffer() {
354        free(m_pStr);
355    }
356
357    void Resize(jsize cbTCharCount) {
358        m_dwSize = cbTCharCount;
359        //It is ok to have non-null terminated string here.
360        //The function is used only for space reservation in staff buffer for
361        //followed data copying process. And that is the reason why we ignore
362        //the special case m_dwSize==0 here.
363        m_pStr = (LPWSTR)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, m_pStr, m_dwSize+1, sizeof(WCHAR) );
364    }
365    //we are in UNICODE now, so LPWSTR:=:LPTSTR
366    operator LPWSTR() { return getNonEmptyString(); }
367    operator LPARAM() { return (LPARAM)getNonEmptyString(); }
368    void *GetData() { return (void *)getNonEmptyString(); }
369    jsize  GetSize() { return m_dwSize; }
370};
371
372
373#endif  /* _AWT_H_ */
374