1 /* 2 * Copyright (c) 2011, 2013, 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 _GLASS_UTILS_ 27 #define _GLASS_UTILS_ 28 29 #ifndef _WIN32_WINNT 30 # error The header should not be included directly. Do #include "common.h" instead. 31 #endif 32 33 #ifndef USER_TIMER_MINIMUM 34 #define USER_TIMER_MINIMUM 0x0000000A 35 #define USER_TIMER_MAXIMUM 0x7FFFFFFF 36 #endif 37 38 #if defined(DEBUG) || defined(_DEBUG) 39 #define ASSERT(condition) \ 40 if (!(condition)) { \ 41 fprintf(stderr, "ERROR: %s (%s, %s, line %d)\n", \ 42 #condition, __FUNCTION__, __FILE__, __LINE__); \ 43 fflush(stderr); \ 44 ::DebugBreak(); \ 45 } 46 #else 47 #define ASSERT(condition) 48 #endif 49 50 #ifdef _WIN64 51 #define jlong_to_ptr(a) ((void*)(a)) 52 #define ptr_to_jlong(a) ((jlong)(a)) 53 #else 54 #define jlong_to_ptr(a) ((void*)(int)(a)) 55 #define ptr_to_jlong(a) ((jlong)(int)(a)) 56 #endif 57 58 #define jbool_to_bool(a) (((a) == JNI_TRUE) ? TRUE : FALSE) 59 #define bool_to_jbool(a) ((a) ? JNI_TRUE : JNI_FALSE) 60 61 #define IS_WINVER_ATLEAST(maj, min) \ 62 (LOBYTE(LOWORD(::GetVersion())) > (maj) || \ 63 LOBYTE(LOWORD(::GetVersion())) == (maj) && \ 64 HIBYTE(LOWORD(::GetVersion())) >= (min)) 65 #define IS_WINXP IS_WINVER_ATLEAST(5, 1) 66 #define IS_WINVISTA IS_WINVER_ATLEAST(6, 0) 67 #define IS_WIN7 IS_WINVER_ATLEAST(6, 1) 68 69 #if defined(DEBUG) || defined(_DEBUG) 70 #define LOG(msg, ...) do { printf(msg, __VA_ARGS__); } while (0) 71 #else 72 #define LOG(msg, ...) do { } while (0) 73 #endif 74 75 /////////////////////////////////////////////////////////// 76 // Java helper routines 77 /////////////////////////////////////////////////////////// 78 79 JavaVM* GetJVM(); 80 JNIEnv* GetEnv(); 81 82 // Returns JNI_TRUE if there are exceptions 83 jboolean CheckAndClearException(JNIEnv *env); 84 85 jint GetModifiers(); 86 87 class JString { 88 public: 89 JString(JNIEnv *env, jstring jString) { 90 init(env, jString, true); 91 } 92 JString(JNIEnv *env, jstring jString, bool autoDelete) { 93 init(env, jString, autoDelete); 94 } 95 96 ~JString() { 97 if (m_wszStr && m_autoDelete) { 98 delete[] m_wszStr; 99 } 100 } 101 102 operator wchar_t*() { return m_wszStr; } 103 104 int length() { return m_len; } 105 106 private: 107 void init(JNIEnv *env, jstring jString, bool autoDelete) { 108 m_len = env->GetStringLength(jString); 109 m_wszStr = new wchar_t[m_len + 1]; 110 env->GetStringRegion(jString, 0, m_len, (jchar *)m_wszStr); 111 m_wszStr[m_len] = L'\0'; 112 m_autoDelete = autoDelete; 113 } 114 115 wchar_t *m_wszStr; 116 int m_len; 117 bool m_autoDelete; 118 }; 119 120 // DNT == double null terminated 121 class DNTString { 122 public: 123 DNTString(int limit) : 124 m_limit(limit), m_length(0), m_substrings(NULL), m_count(0) 125 { 126 wszStr = new wchar_t[limit]; 127 memset(wszStr, 0, limit*sizeof(wchar_t)); 128 } 129 ~DNTString() { 130 if (wszStr) { 131 delete[] wszStr; 132 } 133 if (m_substrings) { 134 delete[] m_substrings; 135 } 136 } 137 138 operator wchar_t*() { return wszStr; } 139 140 size_t length() { return m_length; } 141 142 size_t limit() { return m_limit; } 143 144 void setLimit(size_t limit, bool copy = false) { 145 wchar_t * const oldStr = wszStr; 146 const size_t oldLimit = m_limit; 147 148 m_limit = limit; 149 wszStr = new wchar_t[limit]; 150 memset(wszStr, 0, limit*sizeof(wchar_t)); 151 152 if (copy && oldStr) { 153 wmemcpy_s(wszStr, m_limit - 1, oldStr, min(oldLimit - 1, m_limit - 1)); 154 m_length = min(m_length, m_limit - 2); 155 } 156 157 if (oldStr) { 158 delete[] oldStr; 159 } 160 } 161 162 UINT count() { 163 calculateSubstrings(); 164 return m_count; 165 } 166 167 wchar_t* substring(UINT i) { 168 calculateSubstrings(); 169 return wszStr+m_substrings[i]; 170 } 171 172 // appends the count characters of the src string to the DNT string 173 void append(const wchar_t *wszSrc, const size_t count, bool allowGrow = false) { 174 if (allowGrow) { 175 if (m_length + count > m_limit - 2) { 176 const size_t GROWTH_RATE = 2; // consider parameterizing this const 177 178 setLimit((m_length + count + 2)*GROWTH_RATE, true); 179 } 180 } 181 182 // "-1" because this is a _double_ null terminated string 183 wcsncpy_s(wszStr + m_length, m_limit - m_length - 1, wszSrc, count); 184 m_length += count; 185 if (m_length > m_limit) { 186 m_length = m_limit; 187 } 188 } 189 190 // recalculates the length of the DNT string 191 // use the function when wszStr could be modified directly 192 void calculateLength() { 193 size_t i = 0; 194 while(wszStr[i] != L'\0' || wszStr[i+1] != L'\0') { 195 i++; 196 if (i>= m_limit-1) { 197 i = m_limit; 198 break; 199 } 200 } 201 m_length = i; 202 } 203 204 private: 205 206 void calculateSubstrings() { 207 if (m_substrings) 208 return; 209 210 wchar_t prevChar = '\0'; 211 for (size_t i = 0; i < m_length; i++) { 212 if (prevChar == '\0' && wszStr[i] != '\0') { // new substring 213 m_count++; 214 } 215 prevChar = wszStr[i]; 216 } 217 218 m_substrings = new size_t[m_count]; 219 m_count = 0; 220 prevChar = '\0'; 221 for (size_t i = 0; i < m_length; i++) { 222 if (prevChar == '\0' && wszStr[i] != '\0') { // new substring 223 m_substrings[m_count] = i; 224 m_count++; 225 } 226 prevChar = wszStr[i]; 227 } 228 } 229 230 wchar_t *wszStr; 231 size_t m_length, m_limit; 232 233 size_t *m_substrings; 234 UINT m_count; // the count of the substrings 235 }; 236 237 inline jstring CreateJString(JNIEnv *env, const wchar_t *wszStr) { 238 if (wszStr == NULL) 239 return NULL; 240 jstring jStr = env->NewString((const jchar *)wszStr, jsize(wcslen(wszStr))); 241 if (CheckAndClearException(env)) return NULL; 242 return jStr; 243 } 244 245 inline jstring CreateJString(JNIEnv *env, const char *szStr) { 246 if (szStr == NULL) 247 return NULL; 248 jstring jStr = env->NewStringUTF(szStr); 249 if (CheckAndClearException(env)) return NULL; 250 return jStr; 251 } 252 253 inline jstring ConcatJStrings(JNIEnv *env, jstring str1, jstring str2) { 254 if (str1 == NULL || str2 == NULL) 255 return NULL; 256 jclass cls = env->FindClass("java/lang/String"); 257 if (CheckAndClearException(env)) { 258 return NULL; 259 } 260 jmethodID mid = env->GetMethodID(cls, "concat", "(Ljava/lang/String;)Ljava/lang/String;"); 261 if (CheckAndClearException(env)) return NULL; 262 jstring ret = (jstring)env->CallObjectMethod(str1, mid, str2); 263 CheckAndClearException(env); 264 265 return ret; 266 } 267 268 template <class T> 269 class JLocalRef { 270 JNIEnv* m_env; 271 T m_localJRef; 272 273 public: 274 JLocalRef(JNIEnv* env, T localJRef = NULL) 275 : m_env(env), 276 m_localJRef(localJRef) 277 {} 278 T Detach() { 279 T ret = m_localJRef; 280 m_localJRef = NULL; 281 return ret; 282 } 283 void Attach(T newValue) { 284 if (m_localJRef) { 285 m_env->DeleteLocalRef((jobject)m_localJRef); 286 } 287 m_localJRef = newValue; 288 } 289 290 operator T() { return m_localJRef; } 291 operator bool() { return NULL!=m_localJRef; } 292 bool operator !() { return NULL==m_localJRef; } 293 294 ~JLocalRef() { 295 if (m_localJRef) { 296 m_env->DeleteLocalRef((jobject)m_localJRef); 297 } 298 } 299 }; 300 301 template <class T> 302 class JGlobalRef { 303 T m_globalJRef; 304 305 public: 306 JGlobalRef() : m_globalJRef(NULL) {} 307 308 JGlobalRef(T o) : m_globalJRef(NULL) // make sure it's NULL initially 309 { 310 Attach(GetEnv(), o); 311 } 312 313 void Attach(JNIEnv* env, T localJRef){ 314 if (m_globalJRef) { 315 env->DeleteGlobalRef((jobject)m_globalJRef); 316 } 317 m_globalJRef = (T)(localJRef 318 ? env->NewGlobalRef((jobject)localJRef) 319 : NULL); 320 } 321 322 JGlobalRef<T>& operator = (T localRef) 323 { 324 Attach(GetEnv(), localRef); 325 return *this; 326 } 327 328 operator T() { return m_globalJRef; } 329 operator bool() { return NULL!=m_globalJRef; } 330 bool operator !() { return NULL==m_globalJRef; } 331 332 ~JGlobalRef() { 333 if (m_globalJRef) { 334 GetEnv()->DeleteGlobalRef((jobject)m_globalJRef); 335 } 336 } 337 }; 338 339 340 template <class T> 341 class MemHolder 342 { 343 public: 344 MemHolder(size_t count) 345 { 346 m_pMem = reinterpret_cast<T *>(0==count 347 ? NULL 348 : malloc(count*sizeof(T))); 349 } 350 ~MemHolder(){ 351 free(m_pMem); 352 } 353 354 MemHolder& operator = (MemHolder &r) 355 { 356 if(this != &r){ 357 m_pMem = r.m_pMem; 358 r.m_pMem = NULL; 359 } 360 return *this; 361 } 362 363 inline T *get() { return m_pMem; } 364 inline operator T *() { return m_pMem; } 365 inline operator bool() { return NULL!=m_pMem;} 366 inline bool operator !() { return NULL==m_pMem;} 367 private: 368 T *m_pMem; 369 }; 370 371 typedef JLocalRef<jobject> JLObject; 372 typedef JLocalRef<jstring> JLString; 373 typedef JLocalRef<jclass> JLClass; 374 typedef JLocalRef<jobjectArray> JLObjectArray; 375 376 template <class T> 377 class JArray { 378 public: 379 JArray() : data(NULL) {} 380 ~JArray() 381 { 382 if (data) { 383 GetEnv()->ReleasePrimitiveArrayCritical(array, data, JNI_ABORT); 384 } 385 } 386 387 void Attach(JNIEnv *env, jarray a) 388 { 389 array.Attach(env, a); 390 } 391 392 T* GetPtr() 393 { 394 if (!data && array) { 395 data = (T*)GetEnv()->GetPrimitiveArrayCritical(array, NULL); 396 } 397 return data; 398 } 399 400 operator bool() { return array; } 401 private: 402 JGlobalRef<jarray> array; 403 T * data; 404 }; 405 406 template <class T> 407 class JBufferArray { 408 public: 409 JBufferArray() : data(NULL), offset(0) {} 410 411 void Attach(JNIEnv *env, jobject buf, jarray arr, jint offs) 412 { 413 if (!arr) { 414 data = (T*)env->GetDirectBufferAddress(buf); 415 } else { 416 array.Attach(env, arr); 417 offset = offs; 418 } 419 } 420 421 T* GetPtr() 422 { 423 if (!data && array) { 424 data = array.GetPtr(); 425 data += offset; 426 } 427 return data; 428 } 429 430 operator bool() { return data || array; } 431 432 private: 433 T* data; 434 JArray<T> array; 435 jint offset; 436 }; 437 438 typedef struct _tagJavaIDs { 439 struct { 440 jmethodID notifyFocus; 441 jmethodID notifyFocusDisabled; 442 jmethodID notifyFocusUngrab; 443 jmethodID notifyDestroy; 444 jmethodID notifyDelegatePtr; 445 } Window; 446 struct { 447 jmethodID notifyResize; 448 jmethodID notifyRepaint; 449 jmethodID notifyKey; 450 jmethodID notifyMouse; 451 jmethodID notifyMenu; 452 jmethodID notifyScroll; 453 jmethodID notifyInputMethod; 454 jmethodID notifyInputMethodCandidatePosRequest; 455 456 jmethodID notifyDragEnter; 457 jmethodID notifyDragOver; 458 jmethodID notifyDragLeave; 459 jmethodID notifyDragDrop; 460 461 jmethodID notifyView; 462 463 jmethodID getWidth; 464 jmethodID getHeight; 465 jmethodID getAccessible; 466 467 jfieldID ptr; 468 } View; 469 struct { 470 jmethodID init; 471 } Size; 472 struct { 473 jmethodID attachData; 474 } Pixels; 475 struct { 476 jmethodID getType; 477 jmethodID getNativeCursor; 478 } Cursor; 479 struct { 480 struct { 481 jmethodID getDescription; 482 jmethodID extensionsToArray; 483 } ExtensionFilter; 484 jmethodID createFileChooserResult; 485 } CommonDialogs; 486 struct { 487 jmethodID run; 488 } Runnable; 489 struct { 490 jmethodID add; 491 } List; 492 struct { 493 jmethodID gesturePerformedMID; 494 jmethodID inertiaGestureFinishedMID; 495 jmethodID notifyBeginTouchEventMID; 496 jmethodID notifyNextTouchEventMID; 497 jmethodID notifyEndTouchEventMID; 498 } Gestures; 499 struct { 500 jmethodID init; 501 jmethodID notifySettingsChanged; 502 } Screen; 503 struct { 504 jmethodID reportExceptionMID; 505 jmethodID notifyThemeChangedMID; 506 } Application; 507 } JavaIDs; 508 509 extern JavaIDs javaIDs; 510 511 512 #endif //_GLASS_UTILS_ 513