comparison android/dw.cpp @ 2810:e0ac1ef1c85b

Android: JNI changes to address potential memory/object leaks. While I haven't done any memory leak testing, while researching how to improve performance, it has come to my attention that I should be releasing various objects. Particularly java string related references. Always call DeleteLocalRef() after NewStringUTF() and... Always call ReleaseStringUTFChars() after GetStringUTFChars().
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Tue, 26 Jul 2022 19:40:46 +0000
parents f910da0418f6
children 723b79981427
comparison
equal deleted inserted replaced
2809:f81e92947f4a 2810:e0ac1ef1c85b
76 return JNI_VERSION_1_6; 76 return JNI_VERSION_1_6;
77 } 77 }
78 78
79 jclass _dw_find_class(JNIEnv *env, const char* name) 79 jclass _dw_find_class(JNIEnv *env, const char* name)
80 { 80 {
81 return static_cast<jclass>(env->CallObjectMethod(_dw_class_loader, _dw_class_method, env->NewStringUTF(name))); 81 jstring jname = env->NewStringUTF(name);
82 jclass clazz = static_cast<jclass>(env->CallObjectMethod(_dw_class_loader, _dw_class_method, jname));
83 env->DeleteLocalRef(jname);
84 return clazz;
82 } 85 }
83 86
84 // Do a quick check if an exception occurred... 87 // Do a quick check if an exception occurred...
85 // Display then clear it so we can continue... 88 // Display then clear it so we can continue...
86 // Return TRUE if an exception had occurred 89 // Return TRUE if an exception had occurred
157 * path: The path to the Android app. 160 * path: The path to the Android app.
158 */ 161 */
159 JNIEXPORT void JNICALL 162 JNIEXPORT void JNICALL
160 Java_org_dbsoft_dwindows_DWindows_dwindowsInit(JNIEnv* env, jobject obj, jstring apppath, jstring appcache, jstring appID) 163 Java_org_dbsoft_dwindows_DWindows_dwindowsInit(JNIEnv* env, jobject obj, jstring apppath, jstring appcache, jstring appID)
161 { 164 {
162 char *arg = strdup(env->GetStringUTFChars((jstring)apppath, nullptr)); 165 const char *arg = env->GetStringUTFChars((jstring)apppath, nullptr);
163 const char *cache = env->GetStringUTFChars((jstring)appcache, nullptr); 166 const char *cache = env->GetStringUTFChars((jstring)appcache, nullptr);
164 const char *appid = env->GetStringUTFChars((jstring)appID, nullptr); 167 const char *appid = env->GetStringUTFChars((jstring)appID, nullptr);
165 char *home = getenv("HOME"); 168 char *home = getenv("HOME");
166 169
167 if(!_dw_main_event) 170 if(!_dw_main_event)
183 186
184 if(cache) 187 if(cache)
185 { 188 {
186 /* Store the passed in path for dw_app_dir() */ 189 /* Store the passed in path for dw_app_dir() */
187 strncpy(_dw_exec_dir, cache, MAX_PATH); 190 strncpy(_dw_exec_dir, cache, MAX_PATH);
191 env->ReleaseStringUTFChars(appcache, cache);
188 } 192 }
189 /* Store the best path for dw_user_dir() */ 193 /* Store the best path for dw_user_dir() */
190 if(home) 194 if(home)
191 strncpy(_dw_user_dir, home, MAX_PATH); 195 strncpy(_dw_user_dir, home, MAX_PATH);
192 else if(arg) 196 else if(arg)
195 strcpy(_dw_user_dir, "/"); 199 strcpy(_dw_user_dir, "/");
196 if(appid) 200 if(appid)
197 { 201 {
198 /* Store our reported Android AppID */ 202 /* Store our reported Android AppID */
199 strncpy(_dw_app_id, appid, _DW_APP_ID_SIZE); 203 strncpy(_dw_app_id, appid, _DW_APP_ID_SIZE);
204 env->ReleaseStringUTFChars(appID, appid);
200 } 205 }
201 206
202 /* Launch the new thread to execute dwmain() */ 207 /* Launch the new thread to execute dwmain() */
203 dw_thread_new((void *) _dw_main_launch, arg, 0); 208 dw_thread_new((void *) _dw_main_launch, strdup(arg ? arg : ""), 0);
209
210 if(arg)
211 env->ReleaseStringUTFChars(apppath, arg);
204 } 212 }
205 213
206 typedef struct _dwsighandler 214 typedef struct _dwsighandler
207 { 215 {
208 struct _dwsighandler *next; 216 struct _dwsighandler *next;
306 int (*keypressfunc)(HWND, char, int, int, void *, char *) = (int (* API)(HWND, char, int, int, void *, char *))handler->signalfunction; 314 int (*keypressfunc)(HWND, char, int, int, void *, char *) = (int (* API)(HWND, char, int, int, void *, char *))handler->signalfunction;
307 char *utf8 = (char *)params[1], ch = (char)DW_POINTER_TO_INT(params[3]); 315 char *utf8 = (char *)params[1], ch = (char)DW_POINTER_TO_INT(params[3]);
308 int vk = DW_POINTER_TO_INT(params[4]), special = DW_POINTER_TO_INT(params[5]); 316 int vk = DW_POINTER_TO_INT(params[4]), special = DW_POINTER_TO_INT(params[5]);
309 317
310 retval = keypressfunc(handler->window, ch, (int)vk, special, handler->data, utf8); 318 retval = keypressfunc(handler->window, ch, (int)vk, special, handler->data, utf8);
319 if(utf8)
320 free(utf8);
311 break; 321 break;
312 } 322 }
313 /* Button press and release event */ 323 /* Button press and release event */
314 case _DW_EVENT_BUTTON_PRESS: 324 case _DW_EVENT_BUTTON_PRESS:
315 case _DW_EVENT_BUTTON_RELEASE: 325 case _DW_EVENT_BUTTON_RELEASE:
361 } 371 }
362 /* Container class selection event */ 372 /* Container class selection event */
363 case _DW_EVENT_ITEM_ENTER: 373 case _DW_EVENT_ITEM_ENTER:
364 { 374 {
365 int (*containerselectfunc)(HWND, char *, void *, void *) =(int (* API)(HWND, char *, void *, void *)) handler->signalfunction; 375 int (*containerselectfunc)(HWND, char *, void *, void *) =(int (* API)(HWND, char *, void *, void *)) handler->signalfunction;
366 376 char *text = (char *)params[1];
367 retval = containerselectfunc(handler->window, (char *)params[1], handler->data, params[7]); 377
378 retval = containerselectfunc(handler->window, text, handler->data, params[7]);
379 if(text)
380 free(text);
368 break; 381 break;
369 } 382 }
370 /* Container context menu event */ 383 /* Container context menu event */
371 case _DW_EVENT_ITEM_CONTEXT: 384 case _DW_EVENT_ITEM_CONTEXT:
372 { 385 {
375 void *user = params[7]; 388 void *user = params[7];
376 int x = DW_POINTER_TO_INT(params[3]); 389 int x = DW_POINTER_TO_INT(params[3]);
377 int y = DW_POINTER_TO_INT(params[4]); 390 int y = DW_POINTER_TO_INT(params[4]);
378 391
379 retval = containercontextfunc(handler->window, text, x, y, handler->data, user); 392 retval = containercontextfunc(handler->window, text, x, y, handler->data, user);
393 if(text)
394 free(text);
380 break; 395 break;
381 } 396 }
382 /* Generic selection changed event for several classes */ 397 /* Generic selection changed event for several classes */
383 case _DW_EVENT_LIST_SELECT: 398 case _DW_EVENT_LIST_SELECT:
384 case _DW_EVENT_VALUE_CHANGED: 399 case _DW_EVENT_VALUE_CHANGED:
395 int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))handler->signalfunction; 410 int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))handler->signalfunction;
396 char *text = (char *)params[1]; 411 char *text = (char *)params[1];
397 void *user = params[7]; 412 void *user = params[7];
398 413
399 retval = treeselectfunc(handler->window, (jobject)params[0], text, handler->data, user); 414 retval = treeselectfunc(handler->window, (jobject)params[0], text, handler->data, user);
415 if(text)
416 free(text);
400 break; 417 break;
401 } 418 }
402 /* Set Focus event */ 419 /* Set Focus event */
403 case _DW_EVENT_SET_FOCUS: 420 case _DW_EVENT_SET_FOCUS:
404 { 421 {
438 { 455 {
439 int (* API htmlresultfunc)(HWND, int, char *, void *, void *) = (int (* API)(HWND, int, char *, void *, void *))handler->signalfunction; 456 int (* API htmlresultfunc)(HWND, int, char *, void *, void *) = (int (* API)(HWND, int, char *, void *, void *))handler->signalfunction;
440 char *result = (char *)params[1]; 457 char *result = (char *)params[1];
441 458
442 retval = htmlresultfunc(handler->window, result ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, result, params[7], handler->data); 459 retval = htmlresultfunc(handler->window, result ? DW_ERROR_NONE : DW_ERROR_UNKNOWN, result, params[7], handler->data);
460 if(result)
461 free(result);
443 break; 462 break;
444 } 463 }
445 /* HTML changed event */ 464 /* HTML changed event */
446 case _DW_EVENT_HTML_CHANGED: 465 case _DW_EVENT_HTML_CHANGED:
447 { 466 {
448 int (* API htmlchangedfunc)(HWND, int, char *, void *) = (int (* API)(HWND, int, char *, void *))handler->signalfunction; 467 int (* API htmlchangedfunc)(HWND, int, char *, void *) = (int (* API)(HWND, int, char *, void *))handler->signalfunction;
449 char *uri = (char *)params[1]; 468 char *uri = (char *)params[1];
450 469
451 retval = htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[3]), uri, handler->data); 470 retval = htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[3]), uri, handler->data);
471 if(uri)
472 free(uri);
452 break; 473 break;
453 } 474 }
454 } 475 }
455 } 476 }
456 return retval; 477 return retval;
578 Java_org_dbsoft_dwindows_DWindows_eventHandler(JNIEnv* env, jobject obj, jobject obj1, jobject obj2, 599 Java_org_dbsoft_dwindows_DWindows_eventHandler(JNIEnv* env, jobject obj, jobject obj1, jobject obj2,
579 jint message, jstring str1, jstring str2, 600 jint message, jstring str1, jstring str2,
580 jint inta, jint intb, jint intc, jint intd) { 601 jint inta, jint intb, jint intc, jint intd) {
581 const char *utf81 = str1 ? env->GetStringUTFChars(str1, nullptr) : nullptr; 602 const char *utf81 = str1 ? env->GetStringUTFChars(str1, nullptr) : nullptr;
582 const char *utf82 = str2 ? env->GetStringUTFChars(str2, nullptr) : nullptr; 603 const char *utf82 = str2 ? env->GetStringUTFChars(str2, nullptr) : nullptr;
583 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(obj2), DW_POINTER(utf81), DW_POINTER(utf82), 604 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(obj2), DW_POINTER(utf81 ? strdup(utf81) : nullptr),
605 DW_POINTER(utf82 ? strdup(utf82) : nullptr),
584 DW_INT_TO_POINTER(inta), DW_INT_TO_POINTER(intb), 606 DW_INT_TO_POINTER(inta), DW_INT_TO_POINTER(intb),
585 DW_INT_TO_POINTER(intc), DW_INT_TO_POINTER(intd), nullptr, 607 DW_INT_TO_POINTER(intc), DW_INT_TO_POINTER(intd), nullptr,
586 DW_INT_TO_POINTER(message), nullptr }; 608 DW_INT_TO_POINTER(message), nullptr };
587 609
588 return _dw_event_handler(obj1, params); 610 int retval = _dw_event_handler(obj1, params);
611 if(utf81)
612 env->ReleaseStringUTFChars(str1, utf81);
613 if(utf82)
614 env->ReleaseStringUTFChars(str2, utf82);
615 return retval;
589 } 616 }
590 617
591 /* A more simple method for quicker calls */ 618 /* A more simple method for quicker calls */
592 JNIEXPORT void JNICALL 619 JNIEXPORT void JNICALL
593 Java_org_dbsoft_dwindows_DWindows_eventHandlerSimple(JNIEnv* env, jobject obj, jobject obj1, jint message) 620 Java_org_dbsoft_dwindows_DWindows_eventHandlerSimple(JNIEnv* env, jobject obj, jobject obj1, jint message)
612 /* Handlers for HTML events */ 639 /* Handlers for HTML events */
613 JNIEXPORT void JNICALL 640 JNIEXPORT void JNICALL
614 Java_org_dbsoft_dwindows_DWindows_eventHandlerHTMLResult(JNIEnv* env, jobject obj, jobject obj1, 641 Java_org_dbsoft_dwindows_DWindows_eventHandlerHTMLResult(JNIEnv* env, jobject obj, jobject obj1,
615 jint message, jstring htmlResult, jlong data) { 642 jint message, jstring htmlResult, jlong data) {
616 const char *result = env->GetStringUTFChars(htmlResult, nullptr); 643 const char *result = env->GetStringUTFChars(htmlResult, nullptr);
617 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(result), nullptr, nullptr, nullptr, nullptr, nullptr, 644 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(result ? strdup(result) : nullptr), nullptr,
618 DW_INT_TO_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; 645 nullptr, nullptr, nullptr, nullptr, DW_INT_TO_POINTER(data),
646 DW_INT_TO_POINTER(message), nullptr };
619 647
620 _dw_event_handler(obj1, params); 648 _dw_event_handler(obj1, params);
649 if(result)
650 env->ReleaseStringUTFChars(htmlResult, result);
621 } 651 }
622 652
623 JNIEXPORT void JNICALL 653 JNIEXPORT void JNICALL
624 Java_org_dbsoft_dwindows_DWWebViewClient_eventHandlerHTMLChanged(JNIEnv* env, jobject obj, jobject obj1, 654 Java_org_dbsoft_dwindows_DWWebViewClient_eventHandlerHTMLChanged(JNIEnv* env, jobject obj, jobject obj1,
625 jint message, jstring URI, jint status) { 655 jint message, jstring URI, jint status) {
626 const char *uri = env->GetStringUTFChars(URI, nullptr); 656 const char *uri = env->GetStringUTFChars(URI, nullptr);
627 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(uri), nullptr, DW_INT_TO_POINTER(status), 657 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(uri ? strdup(uri) : nullptr), nullptr,
628 nullptr, nullptr, nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; 658 DW_INT_TO_POINTER(status), nullptr, nullptr, nullptr, nullptr,
659 DW_INT_TO_POINTER(message), nullptr };
629 660
630 _dw_event_handler(obj1, params); 661 _dw_event_handler(obj1, params);
662 if(uri)
663 env->ReleaseStringUTFChars(URI, uri);
631 } 664 }
632 665
633 typedef struct _dwprint 666 typedef struct _dwprint
634 { 667 {
635 int (*drawfunc)(HPRINT, HPIXMAP, int, void *); 668 int (*drawfunc)(HPRINT, HPIXMAP, int, void *);
730 763
731 JNIEXPORT void JNICALL 764 JNIEXPORT void JNICALL
732 Java_org_dbsoft_dwindows_DWindows_eventHandlerContainer(JNIEnv* env, jobject obj, jobject obj1, 765 Java_org_dbsoft_dwindows_DWindows_eventHandlerContainer(JNIEnv* env, jobject obj, jobject obj1,
733 jint message, jstring jtitle, jint x, jint y, jlong data) { 766 jint message, jstring jtitle, jint x, jint y, jlong data) {
734 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; 767 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr;
735 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(title), nullptr, DW_INT_TO_POINTER(x), DW_INT_TO_POINTER(y), 768 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(title ? strdup(title) : nullptr), nullptr,
736 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; 769 DW_INT_TO_POINTER(x), DW_INT_TO_POINTER(y), nullptr, nullptr,
770 DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr };
737 771
738 _dw_event_handler(obj1, params); 772 _dw_event_handler(obj1, params);
773 if(title)
774 env->ReleaseStringUTFChars(jtitle, title);
739 } 775 }
740 776
741 JNIEXPORT void JNICALL 777 JNIEXPORT void JNICALL
742 Java_org_dbsoft_dwindows_DWindows_eventHandlerTree(JNIEnv* env, jobject obj, jobject obj1, 778 Java_org_dbsoft_dwindows_DWindows_eventHandlerTree(JNIEnv* env, jobject obj, jobject obj1,
743 jint message, jobject item, jstring jtitle, jlong data) { 779 jint message, jobject item, jstring jtitle, jlong data) {
744 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; 780 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr;
745 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(item), DW_POINTER(title), nullptr, nullptr, nullptr, 781 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(item), DW_POINTER(title ? strdup(title) : nullptr),
746 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; 782 nullptr, nullptr, nullptr, nullptr, nullptr, DW_POINTER(data),
783 DW_INT_TO_POINTER(message), nullptr };
747 784
748 _dw_event_handler(obj1, params); 785 _dw_event_handler(obj1, params);
786 if(title)
787 env->ReleaseStringUTFChars(jtitle, title);
749 } 788 }
750 789
751 JNIEXPORT void JNICALL 790 JNIEXPORT void JNICALL
752 Java_org_dbsoft_dwindows_DWindows_eventHandlerTreeItem(JNIEnv* env, jobject obj, jobject obj1, 791 Java_org_dbsoft_dwindows_DWindows_eventHandlerTreeItem(JNIEnv* env, jobject obj, jobject obj1,
753 jint message, jobject item) { 792 jint message, jobject item) {
759 798
760 JNIEXPORT void JNICALL 799 JNIEXPORT void JNICALL
761 Java_org_dbsoft_dwindows_DWindows_eventHandlerKey(JNIEnv *env, jobject obj, jobject obj1, jint message, jint ch, 800 Java_org_dbsoft_dwindows_DWindows_eventHandlerKey(JNIEnv *env, jobject obj, jobject obj1, jint message, jint ch,
762 jint vk, jint modifiers, jstring str) { 801 jint vk, jint modifiers, jstring str) {
763 const char *cstr = str ? env->GetStringUTFChars(str, nullptr) : nullptr; 802 const char *cstr = str ? env->GetStringUTFChars(str, nullptr) : nullptr;
764 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(cstr), nullptr, DW_INT_TO_POINTER(ch), DW_INT_TO_POINTER(vk), 803 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(cstr ? strdup(cstr) : nullptr), nullptr,
765 DW_INT_TO_POINTER(modifiers), nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; 804 DW_INT_TO_POINTER(ch), DW_INT_TO_POINTER(vk), DW_INT_TO_POINTER(modifiers),
805 nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr };
766 806
767 _dw_event_handler(obj1, params); 807 _dw_event_handler(obj1, params);
808 if(cstr)
809 env->ReleaseStringUTFChars(str, cstr);
768 } 810 }
769 811
770 /* Handler for Timer events */ 812 /* Handler for Timer events */
771 JNIEXPORT jint JNICALL 813 JNIEXPORT jint JNICALL
772 Java_org_dbsoft_dwindows_DWindows_eventHandlerTimer(JNIEnv* env, jobject obj, jlong sigfunc, jlong data) { 814 Java_org_dbsoft_dwindows_DWindows_eventHandlerTimer(JNIEnv* env, jobject obj, jlong sigfunc, jlong data) {
1127 jmethodID debugMessage = env->GetMethodID(clazz, "debugMessage", 1169 jmethodID debugMessage = env->GetMethodID(clazz, "debugMessage",
1128 "(Ljava/lang/String;)V"); 1170 "(Ljava/lang/String;)V");
1129 // Call the method on the object 1171 // Call the method on the object
1130 env->CallVoidMethod(_dw_obj, debugMessage, jstr); 1172 env->CallVoidMethod(_dw_obj, debugMessage, jstr);
1131 _dw_jni_check_exception(env); 1173 _dw_jni_check_exception(env);
1174 env->DeleteLocalRef(jstr);
1132 } 1175 }
1133 else { 1176 else {
1134 /* Output to stderr, if there is another way to send it 1177 /* Output to stderr, if there is another way to send it
1135 * on the implementation platform, change this. 1178 * on the implementation platform, change this.
1136 */ 1179 */
1171 jmethodID messageBox = env->GetMethodID(clazz, "messageBox", 1214 jmethodID messageBox = env->GetMethodID(clazz, "messageBox",
1172 "(Ljava/lang/String;Ljava/lang/String;I)I"); 1215 "(Ljava/lang/String;Ljava/lang/String;I)I");
1173 // Call the method on the object 1216 // Call the method on the object
1174 retval = env->CallIntMethod(_dw_obj, messageBox, jstrtitle, jstr, flags); 1217 retval = env->CallIntMethod(_dw_obj, messageBox, jstrtitle, jstr, flags);
1175 _dw_jni_check_exception(env); 1218 _dw_jni_check_exception(env);
1219 env->DeleteLocalRef(jstr);
1220 env->DeleteLocalRef(jstrtitle);
1176 } 1221 }
1177 return retval; 1222 return retval;
1178 } 1223 }
1179 1224
1180 /* 1225 /*
1215 { 1260 {
1216 const char *str = env->GetStringUTFChars(jresult, nullptr); 1261 const char *str = env->GetStringUTFChars(jresult, nullptr);
1217 if(str) 1262 if(str)
1218 retval = strdup(str); 1263 retval = strdup(str);
1219 } 1264 }
1265 env->DeleteLocalRef(jstr);
1266 if(path)
1267 env->DeleteLocalRef(path);
1268 if(jext)
1269 env->DeleteLocalRef(jext);
1220 } 1270 }
1221 return retval; 1271 return retval;
1222 } 1272 }
1223 1273
1224 int API dw_file_open(const char *path, int mode) 1274 int API dw_file_open(const char *path, int mode)
1245 jmethodID fileOpen = env->GetMethodID(clazz, "fileOpen", 1295 jmethodID fileOpen = env->GetMethodID(clazz, "fileOpen",
1246 "(Ljava/lang/String;I)I"); 1296 "(Ljava/lang/String;I)I");
1247 // Call the method on the object 1297 // Call the method on the object
1248 retval = (int) env->CallIntMethod(_dw_obj, fileOpen, jstr, (jint) mode); 1298 retval = (int) env->CallIntMethod(_dw_obj, fileOpen, jstr, (jint) mode);
1249 _dw_jni_check_exception(env); 1299 _dw_jni_check_exception(env);
1300 env->DeleteLocalRef(jstr);
1250 } 1301 }
1251 } 1302 }
1252 return retval; 1303 return retval;
1253 } 1304 }
1254 1305
1265 JNIEnv *env; 1316 JNIEnv *env;
1266 1317
1267 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 1318 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
1268 { 1319 {
1269 const char *utf8 = nullptr; 1320 const char *utf8 = nullptr;
1321 char *retval = nullptr;
1270 1322
1271 // First get the class that contains the method you need to call 1323 // First get the class that contains the method you need to call
1272 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 1324 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
1273 // Get the method that you want to call 1325 // Get the method that you want to call
1274 jmethodID clipboardGetText = env->GetMethodID(clazz, "clipboardGetText", 1326 jmethodID clipboardGetText = env->GetMethodID(clazz, "clipboardGetText",
1276 // Call the method on the object 1328 // Call the method on the object
1277 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, clipboardGetText), _DW_REFERENCE_NONE); 1329 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, clipboardGetText), _DW_REFERENCE_NONE);
1278 // Get the UTF8 string result 1330 // Get the UTF8 string result
1279 if(result) 1331 if(result)
1280 utf8 = env->GetStringUTFChars(result, nullptr); 1332 utf8 = env->GetStringUTFChars(result, nullptr);
1281 return utf8 ? strdup(utf8) : nullptr; 1333 if(utf8)
1334 {
1335 retval = strdup(utf8);
1336 env->ReleaseStringUTFChars(result, utf8);
1337 }
1338 return retval;
1282 } 1339 }
1283 return nullptr; 1340 return nullptr;
1284 } 1341 }
1285 1342
1286 /* 1343 /*
1303 jmethodID clipboardSetText = env->GetMethodID(clazz, "clipboardSetText", 1360 jmethodID clipboardSetText = env->GetMethodID(clazz, "clipboardSetText",
1304 "(Ljava/lang/String;)V"); 1361 "(Ljava/lang/String;)V");
1305 // Call the method on the object 1362 // Call the method on the object
1306 env->CallVoidMethod(_dw_obj, clipboardSetText, jstr); 1363 env->CallVoidMethod(_dw_obj, clipboardSetText, jstr);
1307 _dw_jni_check_exception(env); 1364 _dw_jni_check_exception(env);
1365 env->DeleteLocalRef(jstr);
1308 } 1366 }
1309 } 1367 }
1310 1368
1311 /* 1369 /*
1312 * Allocates and initializes a dialog struct. 1370 * Allocates and initializes a dialog struct.
1416 // Get the method that you want to call 1474 // Get the method that you want to call
1417 jmethodID groupBoxNew = env->GetMethodID(clazz, "groupBoxNew", 1475 jmethodID groupBoxNew = env->GetMethodID(clazz, "groupBoxNew",
1418 "(IILjava/lang/String;)Landroid/widget/LinearLayout;"); 1476 "(IILjava/lang/String;)Landroid/widget/LinearLayout;");
1419 // Call the method on the object 1477 // Call the method on the object
1420 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, groupBoxNew, type, pad, jstr), _DW_REFERENCE_WEAK); 1478 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, groupBoxNew, type, pad, jstr), _DW_REFERENCE_WEAK);
1479 if(jstr)
1480 env->DeleteLocalRef(jstr);
1421 return result; 1481 return result;
1422 } 1482 }
1423 return nullptr; 1483 return nullptr;
1424 } 1484 }
1425 1485
1645 // Get the method that you want to call 1705 // Get the method that you want to call
1646 jmethodID buttonNew = env->GetMethodID(clazz, "buttonNew", 1706 jmethodID buttonNew = env->GetMethodID(clazz, "buttonNew",
1647 "(Ljava/lang/String;I)Landroid/widget/Button;"); 1707 "(Ljava/lang/String;I)Landroid/widget/Button;");
1648 // Call the method on the object 1708 // Call the method on the object
1649 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, buttonNew, jstr, (int)cid), _DW_REFERENCE_WEAK); 1709 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, buttonNew, jstr, (int)cid), _DW_REFERENCE_WEAK);
1710 env->DeleteLocalRef(jstr);
1650 return result; 1711 return result;
1651 } 1712 }
1652 return nullptr; 1713 return nullptr;
1653 } 1714 }
1654 1715
1665 // Get the method that you want to call 1726 // Get the method that you want to call
1666 jmethodID entryfieldNew = env->GetMethodID(clazz, "entryfieldNew", 1727 jmethodID entryfieldNew = env->GetMethodID(clazz, "entryfieldNew",
1667 "(Ljava/lang/String;II)Landroid/widget/EditText;"); 1728 "(Ljava/lang/String;II)Landroid/widget/EditText;");
1668 // Call the method on the object 1729 // Call the method on the object
1669 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, entryfieldNew, jstr, (int)cid, password), _DW_REFERENCE_WEAK); 1730 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, entryfieldNew, jstr, (int)cid, password), _DW_REFERENCE_WEAK);
1731 env->DeleteLocalRef(jstr);
1670 return result; 1732 return result;
1671 } 1733 }
1672 return nullptr; 1734 return nullptr;
1673 } 1735 }
1674 /* 1736 /*
1741 // Get the method that you want to call 1803 // Get the method that you want to call
1742 jmethodID bitmapButtonNew = env->GetMethodID(clazz, "bitmapButtonNew", 1804 jmethodID bitmapButtonNew = env->GetMethodID(clazz, "bitmapButtonNew",
1743 "(Ljava/lang/String;I)Landroid/widget/ImageButton;"); 1805 "(Ljava/lang/String;I)Landroid/widget/ImageButton;");
1744 // Call the method on the object 1806 // Call the method on the object
1745 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNew, jstr, (int)resid), _DW_REFERENCE_WEAK); 1807 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNew, jstr, (int)resid), _DW_REFERENCE_WEAK);
1808 env->DeleteLocalRef(jstr);
1746 return result; 1809 return result;
1747 } 1810 }
1748 return nullptr; 1811 return nullptr;
1749 } 1812 }
1750 1813
1765 1828
1766 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 1829 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
1767 { 1830 {
1768 // Construct a String 1831 // Construct a String
1769 jstring jstr = env->NewStringUTF(text); 1832 jstring jstr = env->NewStringUTF(text);
1770 jstring path = env->NewStringUTF(text); 1833 jstring path = env->NewStringUTF(filename);
1771 // First get the class that contains the method you need to call 1834 // First get the class that contains the method you need to call
1772 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 1835 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
1773 // Get the method that you want to call 1836 // Get the method that you want to call
1774 jmethodID bitmapButtonNewFromFile = env->GetMethodID(clazz, "bitmapButtonNewFromFile", 1837 jmethodID bitmapButtonNewFromFile = env->GetMethodID(clazz, "bitmapButtonNewFromFile",
1775 "(Ljava/lang/String;ILjava/lang/String;)Landroid/widget/ImageButton;"); 1838 "(Ljava/lang/String;ILjava/lang/String;)Landroid/widget/ImageButton;");
1776 // Call the method on the object 1839 // Call the method on the object
1777 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNewFromFile, jstr, (int)cid, path), _DW_REFERENCE_WEAK); 1840 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNewFromFile, jstr, (int)cid, path), _DW_REFERENCE_WEAK);
1841 env->DeleteLocalRef(jstr);
1842 env->DeleteLocalRef(path);
1778 return result; 1843 return result;
1779 } 1844 }
1780 return nullptr; 1845 return nullptr;
1781 } 1846 }
1782 1847
1807 // Get the method that you want to call 1872 // Get the method that you want to call
1808 jmethodID bitmapButtonNewFromData = env->GetMethodID(clazz, "bitmapButtonNewFromData", 1873 jmethodID bitmapButtonNewFromData = env->GetMethodID(clazz, "bitmapButtonNewFromData",
1809 "(Ljava/lang/String;I[BI)Landroid/widget/ImageButton;"); 1874 "(Ljava/lang/String;I[BI)Landroid/widget/ImageButton;");
1810 // Call the method on the object 1875 // Call the method on the object
1811 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNewFromData, jstr, (int)cid, bytearray, len), _DW_REFERENCE_WEAK); 1876 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, bitmapButtonNewFromData, jstr, (int)cid, bytearray, len), _DW_REFERENCE_WEAK);
1812 // Clean up after the array now that we are finished 1877 // TODO: Clean up after the array now that we are finished
1813 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0); 1878 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0);
1879 env->DeleteLocalRef(jstr);
1814 return result; 1880 return result;
1815 } 1881 }
1816 return nullptr; 1882 return nullptr;
1817 } 1883 }
1818 1884
1837 // Get the method that you want to call 1903 // Get the method that you want to call
1838 jmethodID spinButtonNew = env->GetMethodID(clazz, "spinButtonNew", 1904 jmethodID spinButtonNew = env->GetMethodID(clazz, "spinButtonNew",
1839 "(Ljava/lang/String;I)Lorg/dbsoft/dwindows/DWSpinButton;"); 1905 "(Ljava/lang/String;I)Lorg/dbsoft/dwindows/DWSpinButton;");
1840 // Call the method on the object 1906 // Call the method on the object
1841 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, spinButtonNew, jstr, (int)cid), _DW_REFERENCE_WEAK); 1907 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, spinButtonNew, jstr, (int)cid), _DW_REFERENCE_WEAK);
1908 env->DeleteLocalRef(jstr);
1842 return result; 1909 return result;
1843 } 1910 }
1844 return nullptr; 1911 return nullptr;
1845 } 1912 }
1846 1913
1939 // Get the method that you want to call 2006 // Get the method that you want to call
1940 jmethodID radioButtonNew = env->GetMethodID(clazz, "radioButtonNew", 2007 jmethodID radioButtonNew = env->GetMethodID(clazz, "radioButtonNew",
1941 "(Ljava/lang/String;I)Landroid/widget/RadioButton;"); 2008 "(Ljava/lang/String;I)Landroid/widget/RadioButton;");
1942 // Call the method on the object 2009 // Call the method on the object
1943 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, radioButtonNew, jstr, (int)cid), _DW_REFERENCE_WEAK); 2010 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, radioButtonNew, jstr, (int)cid), _DW_REFERENCE_WEAK);
2011 env->DeleteLocalRef(jstr);
1944 return result; 2012 return result;
1945 } 2013 }
1946 return nullptr; 2014 return nullptr;
1947 } 2015 }
1948 2016
2153 // Get the method that you want to call 2221 // Get the method that you want to call
2154 jmethodID checkboxNew = env->GetMethodID(clazz, "checkboxNew", 2222 jmethodID checkboxNew = env->GetMethodID(clazz, "checkboxNew",
2155 "(Ljava/lang/String;I)Landroid/widget/CheckBox;"); 2223 "(Ljava/lang/String;I)Landroid/widget/CheckBox;");
2156 // Call the method on the object 2224 // Call the method on the object
2157 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, checkboxNew, jstr, (int)cid), _DW_REFERENCE_WEAK); 2225 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, checkboxNew, jstr, (int)cid), _DW_REFERENCE_WEAK);
2226 env->DeleteLocalRef(jstr);
2158 return result; 2227 return result;
2159 } 2228 }
2160 return nullptr; 2229 return nullptr;
2161 } 2230 }
2162 2231
2256 jmethodID listOrComboBoxAppend = env->GetMethodID(clazz, "listOrComboBoxAppend", 2325 jmethodID listOrComboBoxAppend = env->GetMethodID(clazz, "listOrComboBoxAppend",
2257 "(Landroid/view/View;Ljava/lang/String;)V"); 2326 "(Landroid/view/View;Ljava/lang/String;)V");
2258 // Call the method on the object 2327 // Call the method on the object
2259 env->CallVoidMethod(_dw_obj, listOrComboBoxAppend, handle, jstr); 2328 env->CallVoidMethod(_dw_obj, listOrComboBoxAppend, handle, jstr);
2260 _dw_jni_check_exception(env); 2329 _dw_jni_check_exception(env);
2330 env->DeleteLocalRef(jstr);
2261 } 2331 }
2262 } 2332 }
2263 2333
2264 /* 2334 /*
2265 * Inserts the specified text into the listbox's (or combobox) entry list. 2335 * Inserts the specified text into the listbox's (or combobox) entry list.
2282 jmethodID listOrComboBoxInsert = env->GetMethodID(clazz, "listOrComboBoxInsert", 2352 jmethodID listOrComboBoxInsert = env->GetMethodID(clazz, "listOrComboBoxInsert",
2283 "(Landroid/view/View;Ljava/lang/String;I)V"); 2353 "(Landroid/view/View;Ljava/lang/String;I)V");
2284 // Call the method on the object 2354 // Call the method on the object
2285 env->CallVoidMethod(_dw_obj, listOrComboBoxInsert, handle, jstr, pos); 2355 env->CallVoidMethod(_dw_obj, listOrComboBoxInsert, handle, jstr, pos);
2286 _dw_jni_check_exception(env); 2356 _dw_jni_check_exception(env);
2357 env->DeleteLocalRef(jstr);
2287 } 2358 }
2288 } 2359 }
2289 2360
2290 /* 2361 /*
2291 * Appends the specified text items to the listbox's (or combobox) entry list. 2362 * Appends the specified text items to the listbox's (or combobox) entry list.
2399 // Get the UTF8 string result 2470 // Get the UTF8 string result
2400 if(result) 2471 if(result)
2401 { 2472 {
2402 const char *utf8 = env->GetStringUTFChars(result, nullptr); 2473 const char *utf8 = env->GetStringUTFChars(result, nullptr);
2403 2474
2404 strncpy(buffer, utf8, length); 2475 if(utf8)
2476 {
2477 strncpy(buffer, utf8, length);
2478 env->ReleaseStringUTFChars(result, utf8);
2479 }
2405 } 2480 }
2406 } 2481 }
2407 } 2482 }
2408 2483
2409 /* 2484 /*
2427 jmethodID listOrComboBoxSetText = env->GetMethodID(clazz, "listOrComboBoxSetText", 2502 jmethodID listOrComboBoxSetText = env->GetMethodID(clazz, "listOrComboBoxSetText",
2428 "(Landroid/view/View;ILjava/lang/String;)V"); 2503 "(Landroid/view/View;ILjava/lang/String;)V");
2429 // Call the method on the object 2504 // Call the method on the object
2430 env->CallVoidMethod(_dw_obj, listOrComboBoxSetText, handle, index, jstr); 2505 env->CallVoidMethod(_dw_obj, listOrComboBoxSetText, handle, index, jstr);
2431 _dw_jni_check_exception(env); 2506 _dw_jni_check_exception(env);
2507 env->DeleteLocalRef(jstr);
2432 } 2508 }
2433 } 2509 }
2434 2510
2435 /* 2511 /*
2436 * Returns the index to the item in the list currently selected. 2512 * Returns the index to the item in the list currently selected.
2555 // Get the method that you want to call 2631 // Get the method that you want to call
2556 jmethodID comboBoxNew = env->GetMethodID(clazz, "comboBoxNew", 2632 jmethodID comboBoxNew = env->GetMethodID(clazz, "comboBoxNew",
2557 "(Ljava/lang/String;I)Lorg/dbsoft/dwindows/DWComboBox;"); 2633 "(Ljava/lang/String;I)Lorg/dbsoft/dwindows/DWComboBox;");
2558 // Call the method on the object 2634 // Call the method on the object
2559 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, comboBoxNew, jstr, (int)cid), _DW_REFERENCE_WEAK); 2635 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, comboBoxNew, jstr, (int)cid), _DW_REFERENCE_WEAK);
2636 env->DeleteLocalRef(jstr);
2560 return result; 2637 return result;
2561 } 2638 }
2562 return nullptr; 2639 return nullptr;
2563 } 2640 }
2564 2641
2612 "(Landroid/widget/EditText;Ljava/lang/String;I)I"); 2689 "(Landroid/widget/EditText;Ljava/lang/String;I)I");
2613 // Call the method on the object 2690 // Call the method on the object
2614 retval = env->CallIntMethod(_dw_obj, mleImport, handle, jstr, startpoint); 2691 retval = env->CallIntMethod(_dw_obj, mleImport, handle, jstr, startpoint);
2615 if(_dw_jni_check_exception(env)) 2692 if(_dw_jni_check_exception(env))
2616 retval = 0; 2693 retval = 0;
2694 env->DeleteLocalRef(jstr);
2617 } 2695 }
2618 return retval; 2696 return retval;
2619 } 2697 }
2620 2698
2621 /* 2699 /*
2866 "(Landroid/widget/EditText;Ljava/lang/String;II)I"); 2944 "(Landroid/widget/EditText;Ljava/lang/String;II)I");
2867 // Call the method on the object 2945 // Call the method on the object
2868 retval = env->CallIntMethod(_dw_obj, mleSearch, handle, jstr, point, (jint)flags); 2946 retval = env->CallIntMethod(_dw_obj, mleSearch, handle, jstr, point, (jint)flags);
2869 if(_dw_jni_check_exception(env)) 2947 if(_dw_jni_check_exception(env))
2870 retval = DW_ERROR_UNKNOWN; 2948 retval = DW_ERROR_UNKNOWN;
2949 env->DeleteLocalRef(jstr);
2871 } 2950 }
2872 return retval; 2951 return retval;
2873 } 2952 }
2874 2953
2875 /* 2954 /*
2905 // Get the method that you want to call 2984 // Get the method that you want to call
2906 jmethodID textNew = env->GetMethodID(clazz, "textNew", 2985 jmethodID textNew = env->GetMethodID(clazz, "textNew",
2907 "(Ljava/lang/String;II)Landroid/widget/TextView;"); 2986 "(Ljava/lang/String;II)Landroid/widget/TextView;");
2908 // Call the method on the object 2987 // Call the method on the object
2909 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, textNew, jstr, (int)cid, status), _DW_REFERENCE_WEAK); 2988 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, textNew, jstr, (int)cid, status), _DW_REFERENCE_WEAK);
2989 env->DeleteLocalRef(jstr);
2910 return result; 2990 return result;
2911 } 2991 }
2912 return nullptr; 2992 return nullptr;
2913 } 2993 }
2914 2994
3126 // Call the method on the object 3206 // Call the method on the object
3127 env->CallVoidMethod(_dw_obj, drawLine, handle, pixmap ? pixmap->bitmap : nullptr, x, y, jstr, 3207 env->CallVoidMethod(_dw_obj, drawLine, handle, pixmap ? pixmap->bitmap : nullptr, x, y, jstr,
3128 pixmap ? pixmap->typeface : nullptr, pixmap ? pixmap->fontsize : 0, 3208 pixmap ? pixmap->typeface : nullptr, pixmap ? pixmap->fontsize : 0,
3129 pixmap ? pixmap->handle : nullptr, fgcolor, bgcolor); 3209 pixmap ? pixmap->handle : nullptr, fgcolor, bgcolor);
3130 _dw_jni_check_exception(env); 3210 _dw_jni_check_exception(env);
3211 env->DeleteLocalRef(jstr);
3131 } 3212 }
3132 } 3213 }
3133 3214
3134 /* Query the width and height of a text string. 3215 /* Query the width and height of a text string.
3135 * Parameters: 3216 * Parameters:
3160 3241
3161 if(width) 3242 if(width)
3162 *width = dimensions & 0xFFFF; 3243 *width = dimensions & 0xFFFF;
3163 if(height) 3244 if(height)
3164 *height = (dimensions >> 32) & 0xFFFF; 3245 *height = (dimensions >> 32) & 0xFFFF;
3246 env->DeleteLocalRef(jstr);
3165 } 3247 }
3166 } 3248 }
3167 3249
3168 /* Draw a polygon on a window (preferably a render window). 3250 /* Draw a polygon on a window (preferably a render window).
3169 * Parameters: 3251 * Parameters:
3318 jmethodID treeInsertAfter = env->GetMethodID(clazz, "treeInsertAfter", 3400 jmethodID treeInsertAfter = env->GetMethodID(clazz, "treeInsertAfter",
3319 "(Lorg/dbsoft/dwindows/DWTree;Lorg/dbsoft/dwindows/DWTreeItem;Ljava/lang/String;Landroid/graphics/drawable/Drawable;Lorg/dbsoft/dwindows/DWTreeItem;J)Lorg/dbsoft/dwindows/DWTreeItem;"); 3401 "(Lorg/dbsoft/dwindows/DWTree;Lorg/dbsoft/dwindows/DWTreeItem;Ljava/lang/String;Landroid/graphics/drawable/Drawable;Lorg/dbsoft/dwindows/DWTreeItem;J)Lorg/dbsoft/dwindows/DWTreeItem;");
3320 // Call the method on the object 3402 // Call the method on the object
3321 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, treeInsertAfter, handle, item, 3403 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, treeInsertAfter, handle, item,
3322 jstr, icon, parent, (jlong)itemdata), _DW_REFERENCE_WEAK); 3404 jstr, icon, parent, (jlong)itemdata), _DW_REFERENCE_WEAK);
3405 env->DeleteLocalRef(jstr);
3323 return result; 3406 return result;
3324 } 3407 }
3325 return nullptr; 3408 return nullptr;
3326 } 3409 }
3327 3410
3354 JNIEnv *env; 3437 JNIEnv *env;
3355 3438
3356 if(handle && item && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 3439 if(handle && item && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
3357 { 3440 {
3358 const char *utf8 = nullptr; 3441 const char *utf8 = nullptr;
3442 char *retval = nullptr;
3359 3443
3360 // First get the class that contains the method you need to call 3444 // First get the class that contains the method you need to call
3361 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 3445 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
3362 // Get the method that you want to call 3446 // Get the method that you want to call
3363 jmethodID treeGetTitle = env->GetMethodID(clazz, "treeGetTitle", 3447 jmethodID treeGetTitle = env->GetMethodID(clazz, "treeGetTitle",
3365 // Call the method on the object 3449 // Call the method on the object
3366 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, treeGetTitle, handle, item), _DW_REFERENCE_NONE); 3450 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, treeGetTitle, handle, item), _DW_REFERENCE_NONE);
3367 // Get the UTF8 string result 3451 // Get the UTF8 string result
3368 if(result) 3452 if(result)
3369 utf8 = env->GetStringUTFChars(result, nullptr); 3453 utf8 = env->GetStringUTFChars(result, nullptr);
3370 return utf8 ? strdup(utf8) : nullptr; 3454 if(utf8)
3455 {
3456 retval = strdup(utf8);
3457 env->ReleaseStringUTFChars(result, utf8);
3458 }
3371 } 3459 }
3372 return nullptr; 3460 return nullptr;
3373 } 3461 }
3374 3462
3375 /* 3463 /*
3419 // Get the method that you want to call 3507 // Get the method that you want to call
3420 jmethodID treeItemChange = env->GetMethodID(clazz, "treeItemChange", 3508 jmethodID treeItemChange = env->GetMethodID(clazz, "treeItemChange",
3421 "(Lorg/dbsoft/dwindows/DWTree;Lorg/dbsoft/dwindows/DWTreeItem;Ljava/lang/String;Landroid/graphics/drawable/Drawable;)V"); 3509 "(Lorg/dbsoft/dwindows/DWTree;Lorg/dbsoft/dwindows/DWTreeItem;Ljava/lang/String;Landroid/graphics/drawable/Drawable;)V");
3422 // Call the method on the object 3510 // Call the method on the object
3423 env->CallVoidMethod(_dw_obj, treeItemChange, handle, item, jstr, icon); 3511 env->CallVoidMethod(_dw_obj, treeItemChange, handle, item, jstr, icon);
3512 _dw_jni_check_exception(env);
3513 env->DeleteLocalRef(jstr);
3424 } 3514 }
3425 } 3515 }
3426 3516
3427 /* 3517 /*
3428 * Sets the item data of a tree item. 3518 * Sets the item data of a tree item.
3641 "(Landroid/widget/ListView;Ljava/lang/String;I)V"); 3731 "(Landroid/widget/ListView;Ljava/lang/String;I)V");
3642 // Call the method on the object 3732 // Call the method on the object
3643 env->CallVoidMethod(_dw_obj, containerNew, handle, jstr, (int)flags[z]); 3733 env->CallVoidMethod(_dw_obj, containerNew, handle, jstr, (int)flags[z]);
3644 if(_dw_jni_check_exception(env)) 3734 if(_dw_jni_check_exception(env))
3645 retval = DW_ERROR_GENERAL; 3735 retval = DW_ERROR_GENERAL;
3736 env->DeleteLocalRef(jstr);
3646 } 3737 }
3647 } 3738 }
3648 } 3739 }
3649 return retval; 3740 return retval;
3650 } 3741 }
3759 jmethodID containerChangeItem = env->GetMethodID(clazz, "containerChangeItemString", 3850 jmethodID containerChangeItem = env->GetMethodID(clazz, "containerChangeItemString",
3760 "(Landroid/widget/ListView;IILjava/lang/String;)V"); 3851 "(Landroid/widget/ListView;IILjava/lang/String;)V");
3761 // Call the method on the object 3852 // Call the method on the object
3762 env->CallVoidMethod(_dw_obj, containerChangeItem, handle, column, row, jstr); 3853 env->CallVoidMethod(_dw_obj, containerChangeItem, handle, column, row, jstr);
3763 _dw_jni_check_exception(env); 3854 _dw_jni_check_exception(env);
3855 env->DeleteLocalRef(jstr);
3764 } 3856 }
3765 } 3857 }
3766 else if((columntype & DW_CFA_ULONG)) 3858 else if((columntype & DW_CFA_ULONG))
3767 { 3859 {
3768 ULONG num = *((ULONG *)data); 3860 ULONG num = *((ULONG *)data);
4044 jmethodID containerChangeRowTitle = env->GetMethodID(clazz, "containerChangeRowTitle", 4136 jmethodID containerChangeRowTitle = env->GetMethodID(clazz, "containerChangeRowTitle",
4045 "(Landroid/widget/ListView;ILjava/lang/String;)V"); 4137 "(Landroid/widget/ListView;ILjava/lang/String;)V");
4046 // Call the method on the object 4138 // Call the method on the object
4047 env->CallVoidMethod(_dw_obj, containerChangeRowTitle, handle, row, jstr); 4139 env->CallVoidMethod(_dw_obj, containerChangeRowTitle, handle, row, jstr);
4048 _dw_jni_check_exception(env); 4140 _dw_jni_check_exception(env);
4141 env->DeleteLocalRef(jstr);
4049 } 4142 }
4050 } 4143 }
4051 4144
4052 /* 4145 /*
4053 * Sets the title of a row in the container. 4146 * Sets the title of a row in the container.
4169 } else { 4262 } else {
4170 // First get the class that contains the method you need to call 4263 // First get the class that contains the method you need to call
4171 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 4264 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
4172 // Get the method that you want to call 4265 // Get the method that you want to call
4173 jmethodID containerGetTitleStart = env->GetMethodID(clazz, "containerGetTitleStart", 4266 jmethodID containerGetTitleStart = env->GetMethodID(clazz, "containerGetTitleStart",
4174 "(Landroid/widget/ListView;I)Ljava/lang/String;"); 4267 "(Landroid/widget/ListView;I)Ljava/lang/String;");
4175 // Call the method on the object 4268 // Call the method on the object
4176 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, containerGetTitleStart, handle, (jint)flags), _DW_REFERENCE_NONE); 4269 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, containerGetTitleStart, handle, (jint)flags), _DW_REFERENCE_NONE);
4177 char *str; 4270 if(jstr)
4178 4271 {
4179 if(jstr && (str = (char *)env->GetStringUTFChars(jstr, nullptr))) 4272 const char *str = env->GetStringUTFChars(jstr, nullptr);
4180 retval = strdup(str); 4273
4274 if(str)
4275 {
4276 retval = strdup(str);
4277 env->ReleaseStringUTFChars(jstr, str);
4278 }
4279 }
4181 } 4280 }
4182 } 4281 }
4183 return retval; 4282 return retval;
4184 } 4283 }
4185 4284
4216 // Get the method that you want to call 4315 // Get the method that you want to call
4217 jmethodID containerGetTitleNext = env->GetMethodID(clazz, "containerGetTitleNext", 4316 jmethodID containerGetTitleNext = env->GetMethodID(clazz, "containerGetTitleNext",
4218 "(Landroid/widget/ListView;I)Ljava/lang/String;"); 4317 "(Landroid/widget/ListView;I)Ljava/lang/String;");
4219 // Call the method on the object 4318 // Call the method on the object
4220 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, containerGetTitleNext, handle, (jint)flags), _DW_REFERENCE_NONE); 4319 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, containerGetTitleNext, handle, (jint)flags), _DW_REFERENCE_NONE);
4221 char *str; 4320 if(jstr)
4222 4321 {
4223 if(jstr && (str = (char *)env->GetStringUTFChars(jstr, nullptr))) 4322 const char *str = env->GetStringUTFChars(jstr, nullptr);
4224 retval = strdup(str); 4323
4324 if(str)
4325 {
4326 retval = strdup(str);
4327 env->ReleaseStringUTFChars(jstr, str);
4328 }
4329 }
4225 } 4330 }
4226 } 4331 }
4227 return retval; 4332 return retval;
4228 } 4333 }
4229 4334
4247 jmethodID containerCursor = env->GetMethodID(clazz, "containerCursor", 4352 jmethodID containerCursor = env->GetMethodID(clazz, "containerCursor",
4248 "(Landroid/widget/ListView;Ljava/lang/String;)V"); 4353 "(Landroid/widget/ListView;Ljava/lang/String;)V");
4249 // Call the method on the object 4354 // Call the method on the object
4250 env->CallVoidMethod(_dw_obj, containerCursor, handle, jstr); 4355 env->CallVoidMethod(_dw_obj, containerCursor, handle, jstr);
4251 _dw_jni_check_exception(env); 4356 _dw_jni_check_exception(env);
4357 if(jstr)
4358 env->DeleteLocalRef(jstr);
4252 } 4359 }
4253 } 4360 }
4254 4361
4255 /* 4362 /*
4256 * Cursors the item with the data speficied, and scrolls to that item. 4363 * Cursors the item with the data speficied, and scrolls to that item.
4295 jmethodID containerRowDeleteByTitle = env->GetMethodID(clazz, "containerRowDeleteByTitle", 4402 jmethodID containerRowDeleteByTitle = env->GetMethodID(clazz, "containerRowDeleteByTitle",
4296 "(Landroid/widget/ListView;Ljava/lang/String;)V"); 4403 "(Landroid/widget/ListView;Ljava/lang/String;)V");
4297 // Call the method on the object 4404 // Call the method on the object
4298 env->CallVoidMethod(_dw_obj, containerRowDeleteByTitle, handle, jstr); 4405 env->CallVoidMethod(_dw_obj, containerRowDeleteByTitle, handle, jstr);
4299 _dw_jni_check_exception(env); 4406 _dw_jni_check_exception(env);
4407 if(jstr)
4408 env->DeleteLocalRef(jstr);
4300 } 4409 }
4301 } 4410 }
4302 4411
4303 /* 4412 /*
4304 * Deletes the item with the data speficied. 4413 * Deletes the item with the data speficied.
4377 jmethodID iconNew = env->GetMethodID(clazz, "iconNew", 4486 jmethodID iconNew = env->GetMethodID(clazz, "iconNew",
4378 "(Ljava/lang/String;[BII)Landroid/graphics/drawable/Drawable;"); 4487 "(Ljava/lang/String;[BII)Landroid/graphics/drawable/Drawable;");
4379 // Call the method on the object 4488 // Call the method on the object
4380 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, iconNew, 4489 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, iconNew,
4381 file, bytearray, len, resid), _DW_REFERENCE_STRONG); 4490 file, bytearray, len, resid), _DW_REFERENCE_STRONG);
4382 // Clean up after the array now that we are finished 4491 // TODO: Clean up after the array now that we are finished
4383 //if(bytearray) 4492 //if(bytearray)
4384 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0); 4493 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0);
4494 if(file)
4495 env->DeleteLocalRef(file);
4385 return result; 4496 return result;
4386 } 4497 }
4387 return nullptr; 4498 return nullptr;
4388 } 4499 }
4389 4500
4567 { 4678 {
4568 JNIEnv *env; 4679 JNIEnv *env;
4569 4680
4570 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 4681 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
4571 { 4682 {
4572 // Construct a string
4573 jstring file = nullptr;
4574 if(filename)
4575 file = env->NewStringUTF(filename);
4576 // Construct a byte array 4683 // Construct a byte array
4577 jbyteArray bytearray = nullptr; 4684 jbyteArray bytearray = nullptr;
4578 if(data && len > 0) 4685 if(data && len > 0)
4579 { 4686 {
4580 bytearray = env->NewByteArray(len); 4687 bytearray = env->NewByteArray(len);
4581 env->SetByteArrayRegion(bytearray, 0, len, reinterpret_cast<const jbyte *>(data)); 4688 env->SetByteArrayRegion(bytearray, 0, len, reinterpret_cast<const jbyte *>(data));
4582 } 4689 }
4583 if(!_dw_jni_check_exception(env)) 4690 if(!_dw_jni_check_exception(env))
4584 { 4691 {
4692 // Construct a string
4693 jstring file = nullptr;
4694 if(filename)
4695 file = env->NewStringUTF(filename);
4585 // First get the class that contains the method you need to call 4696 // First get the class that contains the method you need to call
4586 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 4697 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
4587 // Get the method that you want to call 4698 // Get the method that you want to call
4588 jmethodID pixmapNew = env->GetMethodID(clazz, "pixmapNew", 4699 jmethodID pixmapNew = env->GetMethodID(clazz, "pixmapNew",
4589 "(IILjava/lang/String;[BII)Landroid/graphics/Bitmap;"); 4700 "(IILjava/lang/String;[BII)Landroid/graphics/Bitmap;");
4592 (jint) width, 4703 (jint) width,
4593 (jint) height, 4704 (jint) height,
4594 file, bytearray, len, 4705 file, bytearray, len,
4595 resid), 4706 resid),
4596 _DW_REFERENCE_STRONG); 4707 _DW_REFERENCE_STRONG);
4597 // Clean up after the array now that we are finished 4708 // TODO: Clean up after the array now that we are finished
4598 //if(bytearray) 4709 //if(bytearray)
4599 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0); 4710 //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0);
4711 if(file)
4712 env->DeleteLocalRef(file);
4600 return result; 4713 return result;
4601 } 4714 }
4602 } 4715 }
4603 return nullptr; 4716 return nullptr;
4604 } 4717 }
4789 pixmap->typeface = typeface; 4902 pixmap->typeface = typeface;
4790 if(oldtypeface) 4903 if(oldtypeface)
4791 env->DeleteGlobalRef(oldtypeface); 4904 env->DeleteGlobalRef(oldtypeface);
4792 pixmap->fontsize = atoi(fontname); 4905 pixmap->fontsize = atoi(fontname);
4793 } 4906 }
4907 env->DeleteLocalRef(jstr);
4794 return DW_ERROR_NONE; 4908 return DW_ERROR_NONE;
4795 } 4909 }
4796 return DW_ERROR_GENERAL; 4910 return DW_ERROR_GENERAL;
4797 } 4911 }
4798 4912
5001 * DW_ERROR_NONE (0) on success. 5115 * DW_ERROR_NONE (0) on success.
5002 */ 5116 */
5003 int API dw_html_raw(HWND handle, const char *string) 5117 int API dw_html_raw(HWND handle, const char *string)
5004 { 5118 {
5005 JNIEnv *env; 5119 JNIEnv *env;
5120 int retval = DW_ERROR_GENERAL;
5006 5121
5007 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 5122 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
5008 { 5123 {
5009 // Construct a String 5124 // Construct a String
5010 jstring jstr = env->NewStringUTF(string); 5125 jstring jstr = env->NewStringUTF(string);
5014 jmethodID htmlRaw = env->GetMethodID(clazz, "htmlRaw", 5129 jmethodID htmlRaw = env->GetMethodID(clazz, "htmlRaw",
5015 "(Landroid/webkit/WebView;Ljava/lang/String;)V"); 5130 "(Landroid/webkit/WebView;Ljava/lang/String;)V");
5016 // Call the method on the object 5131 // Call the method on the object
5017 env->CallVoidMethod(_dw_obj, htmlRaw, handle, jstr); 5132 env->CallVoidMethod(_dw_obj, htmlRaw, handle, jstr);
5018 if(!_dw_jni_check_exception(env)) 5133 if(!_dw_jni_check_exception(env))
5019 return DW_ERROR_NONE; 5134 retval = DW_ERROR_NONE;
5020 } 5135 env->DeleteLocalRef(jstr);
5021 return DW_ERROR_GENERAL; 5136 }
5137 return retval;
5022 } 5138 }
5023 5139
5024 /* 5140 /*
5025 * Render file or web page in the embedded HTML widget.. 5141 * Render file or web page in the embedded HTML widget..
5026 * Parameters: 5142 * Parameters:
5031 * DW_ERROR_NONE (0) on success. 5147 * DW_ERROR_NONE (0) on success.
5032 */ 5148 */
5033 int API dw_html_url(HWND handle, const char *url) 5149 int API dw_html_url(HWND handle, const char *url)
5034 { 5150 {
5035 JNIEnv *env; 5151 JNIEnv *env;
5152 int retval = DW_ERROR_GENERAL;
5036 5153
5037 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 5154 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
5038 { 5155 {
5039 // Construct a String 5156 // Construct a String
5040 jstring jstr = env->NewStringUTF(url); 5157 jstring jstr = env->NewStringUTF(url);
5044 jmethodID htmlLoadURL = env->GetMethodID(clazz, "htmlLoadURL", 5161 jmethodID htmlLoadURL = env->GetMethodID(clazz, "htmlLoadURL",
5045 "(Landroid/webkit/WebView;Ljava/lang/String;)V"); 5162 "(Landroid/webkit/WebView;Ljava/lang/String;)V");
5046 // Call the method on the object 5163 // Call the method on the object
5047 env->CallVoidMethod(_dw_obj, htmlLoadURL, handle, jstr); 5164 env->CallVoidMethod(_dw_obj, htmlLoadURL, handle, jstr);
5048 if(!_dw_jni_check_exception(env)) 5165 if(!_dw_jni_check_exception(env))
5049 return DW_ERROR_NONE; 5166 retval = DW_ERROR_NONE;
5050 } 5167 env->DeleteLocalRef(jstr);
5051 return DW_ERROR_GENERAL; 5168 }
5169 return retval;
5052 } 5170 }
5053 5171
5054 /* 5172 /*
5055 * Executes the javascript contained in "script" in the HTML window. 5173 * Executes the javascript contained in "script" in the HTML window.
5056 * Parameters: 5174 * Parameters:
5062 * DW_ERROR_NONE (0) on success. 5180 * DW_ERROR_NONE (0) on success.
5063 */ 5181 */
5064 int API dw_html_javascript_run(HWND handle, const char *script, void *scriptdata) 5182 int API dw_html_javascript_run(HWND handle, const char *script, void *scriptdata)
5065 { 5183 {
5066 JNIEnv *env; 5184 JNIEnv *env;
5185 int retval = DW_ERROR_GENERAL;
5067 5186
5068 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 5187 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
5069 { 5188 {
5070 // Construct a String 5189 // Construct a String
5071 jstring jstr = env->NewStringUTF(script); 5190 jstring jstr = env->NewStringUTF(script);
5075 jmethodID htmlJavascriptRun = env->GetMethodID(clazz, "htmlJavascriptRun", 5194 jmethodID htmlJavascriptRun = env->GetMethodID(clazz, "htmlJavascriptRun",
5076 "(Landroid/webkit/WebView;Ljava/lang/String;J)V"); 5195 "(Landroid/webkit/WebView;Ljava/lang/String;J)V");
5077 // Call the method on the object 5196 // Call the method on the object
5078 env->CallVoidMethod(_dw_obj, htmlJavascriptRun, handle, jstr, (jlong)scriptdata); 5197 env->CallVoidMethod(_dw_obj, htmlJavascriptRun, handle, jstr, (jlong)scriptdata);
5079 if(!_dw_jni_check_exception(env)) 5198 if(!_dw_jni_check_exception(env))
5080 return DW_ERROR_NONE; 5199 retval = DW_ERROR_NONE;
5081 } 5200 env->DeleteLocalRef(jstr);
5082 return DW_ERROR_UNKNOWN; 5201 }
5202 return retval;
5083 } 5203 }
5084 5204
5085 /* 5205 /*
5086 * Create a new HTML window (widget) to be packed. 5206 * Create a new HTML window (widget) to be packed.
5087 * Parameters: 5207 * Parameters:
5308 // Get the method that you want to call 5428 // Get the method that you want to call
5309 jmethodID menuAppendItem = env->GetMethodID(clazz, "menuAppendItem", 5429 jmethodID menuAppendItem = env->GetMethodID(clazz, "menuAppendItem",
5310 "(Lorg/dbsoft/dwindows/DWMenu;Ljava/lang/String;IIIILorg/dbsoft/dwindows/DWMenu;)Lorg/dbsoft/dwindows/DWMenuItem;"); 5430 "(Lorg/dbsoft/dwindows/DWMenu;Ljava/lang/String;IIIILorg/dbsoft/dwindows/DWMenu;)Lorg/dbsoft/dwindows/DWMenuItem;");
5311 // Call the method on the object 5431 // Call the method on the object
5312 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, menuAppendItem, menux, jstr, (int)itemid, (int)flags, end, check, submenux), _DW_REFERENCE_WEAK); 5432 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, menuAppendItem, menux, jstr, (int)itemid, (int)flags, end, check, submenux), _DW_REFERENCE_WEAK);
5433 env->DeleteLocalRef(jstr);
5313 return result; 5434 return result;
5314 } 5435 }
5315 return nullptr; 5436 return nullptr;
5316 } 5437 }
5317 5438
5500 jmethodID notebookPageSetText = env->GetMethodID(clazz, "notebookPageSetText", 5621 jmethodID notebookPageSetText = env->GetMethodID(clazz, "notebookPageSetText",
5501 "(Landroid/widget/RelativeLayout;JLjava/lang/String;)V"); 5622 "(Landroid/widget/RelativeLayout;JLjava/lang/String;)V");
5502 // Call the method on the object 5623 // Call the method on the object
5503 env->CallVoidMethod(_dw_obj, notebookPageSetText, handle, (jlong)pageid, jstr); 5624 env->CallVoidMethod(_dw_obj, notebookPageSetText, handle, (jlong)pageid, jstr);
5504 _dw_jni_check_exception(env); 5625 _dw_jni_check_exception(env);
5626 env->DeleteLocalRef(jstr);
5505 } 5627 }
5506 } 5628 }
5507 5629
5508 /* 5630 /*
5509 * Sets the text on the specified notebook tab status area. 5631 * Sets the text on the specified notebook tab status area.
5562 // Get the method that you want to call 5684 // Get the method that you want to call
5563 jmethodID windowNew = env->GetMethodID(clazz, "windowNew", 5685 jmethodID windowNew = env->GetMethodID(clazz, "windowNew",
5564 "(Ljava/lang/String;I)Landroid/widget/LinearLayout;"); 5686 "(Ljava/lang/String;I)Landroid/widget/LinearLayout;");
5565 // Call the method on the object 5687 // Call the method on the object
5566 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowNew, jstr, (int)flStyle), _DW_REFERENCE_WEAK); 5688 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowNew, jstr, (int)flStyle), _DW_REFERENCE_WEAK);
5689 env->DeleteLocalRef(jstr);
5567 return result; 5690 return result;
5568 } 5691 }
5569 return nullptr; 5692 return nullptr;
5570 } 5693 }
5571 5694
5810 * DW_ERROR_NONE (0) on success. 5933 * DW_ERROR_NONE (0) on success.
5811 */ 5934 */
5812 int API dw_window_set_font(HWND handle, const char *fontname) 5935 int API dw_window_set_font(HWND handle, const char *fontname)
5813 { 5936 {
5814 JNIEnv *env; 5937 JNIEnv *env;
5938 int retval = DW_ERROR_GENERAL;
5815 5939
5816 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 5940 if(handle && (env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
5817 { 5941 {
5818 // Construct a string 5942 // Construct a string
5819 jstring jstr = env->NewStringUTF(fontname); 5943 jstring jstr = env->NewStringUTF(fontname);
5823 jmethodID windowSetFont = env->GetMethodID(clazz, "windowSetFont", 5947 jmethodID windowSetFont = env->GetMethodID(clazz, "windowSetFont",
5824 "(Landroid/view/View;Ljava/lang/String;)V"); 5948 "(Landroid/view/View;Ljava/lang/String;)V");
5825 // Call the method on the object 5949 // Call the method on the object
5826 env->CallVoidMethod(_dw_obj, windowSetFont, handle, jstr); 5950 env->CallVoidMethod(_dw_obj, windowSetFont, handle, jstr);
5827 if(!_dw_jni_check_exception(env)) 5951 if(!_dw_jni_check_exception(env))
5828 return DW_ERROR_NONE; 5952 retval = DW_ERROR_NONE;
5829 } 5953 env->DeleteLocalRef(jstr);
5830 return DW_ERROR_GENERAL; 5954 }
5955 return retval;
5831 } 5956 }
5832 5957
5833 /* 5958 /*
5834 * Returns the current font for the specified window. 5959 * Returns the current font for the specified window.
5835 * Parameters: 5960 * Parameters:
5851 "(Landroid/view/View;)Ljava/lang/String;"); 5976 "(Landroid/view/View;)Ljava/lang/String;");
5852 // Call the method on the object 5977 // Call the method on the object
5853 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowGetFont, handle), _DW_REFERENCE_NONE); 5978 jstring jstr = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowGetFont, handle), _DW_REFERENCE_NONE);
5854 5979
5855 if(jstr) 5980 if(jstr)
5856 fontname = strdup(env->GetStringUTFChars(jstr, nullptr)); 5981 {
5982 const char *str = env->GetStringUTFChars(jstr, nullptr);
5983
5984 if(str)
5985 {
5986 fontname = strdup(str);
5987 env->ReleaseStringUTFChars(jstr, str);
5988 }
5989 }
5857 } 5990 }
5858 return fontname; 5991 return fontname;
5859 } 5992 }
5860 5993
5861 /* Allows the user to choose a font using the system's font chooser dialog. 5994 /* Allows the user to choose a font using the system's font chooser dialog.
5917 JNIEnv *env; 6050 JNIEnv *env;
5918 6051
5919 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) 6052 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
5920 { 6053 {
5921 const char *utf8 = nullptr; 6054 const char *utf8 = nullptr;
6055 char *retval = nullptr;
5922 6056
5923 // First get the class that contains the method you need to call 6057 // First get the class that contains the method you need to call
5924 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); 6058 jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
5925 // Get the method that you want to call 6059 // Get the method that you want to call
5926 jmethodID windowGetText = env->GetMethodID(clazz, "windowGetText", 6060 jmethodID windowGetText = env->GetMethodID(clazz, "windowGetText",
5928 // Call the method on the object 6062 // Call the method on the object
5929 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowGetText, handle), _DW_REFERENCE_NONE); 6063 jstring result = (jstring)_dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, windowGetText, handle), _DW_REFERENCE_NONE);
5930 // Get the UTF8 string result 6064 // Get the UTF8 string result
5931 if(result) 6065 if(result)
5932 utf8 = env->GetStringUTFChars(result, nullptr); 6066 utf8 = env->GetStringUTFChars(result, nullptr);
5933 return utf8 ? strdup(utf8) : nullptr; 6067 if(utf8)
6068 {
6069 retval = strdup(utf8);
6070 env->ReleaseStringUTFChars(result, utf8);
6071 }
5934 } 6072 }
5935 return nullptr; 6073 return nullptr;
5936 } 6074 }
5937 6075
5938 /* 6076 /*
5955 jmethodID windowSetText = env->GetMethodID(clazz, "windowSetText", 6093 jmethodID windowSetText = env->GetMethodID(clazz, "windowSetText",
5956 "(Landroid/view/View;Ljava/lang/String;)V"); 6094 "(Landroid/view/View;Ljava/lang/String;)V");
5957 // Call the method on the object 6095 // Call the method on the object
5958 env->CallVoidMethod(_dw_obj, windowSetText, handle, jstr); 6096 env->CallVoidMethod(_dw_obj, windowSetText, handle, jstr);
5959 _dw_jni_check_exception(env); 6097 _dw_jni_check_exception(env);
6098 env->DeleteLocalRef(jstr);
5960 } 6099 }
5961 } 6100 }
5962 6101
5963 /* 6102 /*
5964 * Sets the text used for a given window's floating bubble help. 6103 * Sets the text used for a given window's floating bubble help.
6073 jmethodID windowSetBitmapFromData = env->GetMethodID(clazz, "windowSetBitmap", 6212 jmethodID windowSetBitmapFromData = env->GetMethodID(clazz, "windowSetBitmap",
6074 "(Landroid/view/View;ILjava/lang/String;)V"); 6213 "(Landroid/view/View;ILjava/lang/String;)V");
6075 // Call the method on the object 6214 // Call the method on the object
6076 env->CallVoidMethod(_dw_obj, windowSetBitmapFromData, handle, (int)resid, jstr); 6215 env->CallVoidMethod(_dw_obj, windowSetBitmapFromData, handle, (int)resid, jstr);
6077 _dw_jni_check_exception(env); 6216 _dw_jni_check_exception(env);
6217 if(jstr)
6218 env->DeleteLocalRef(jstr);
6078 } 6219 }
6079 } 6220 }
6080 6221
6081 /* 6222 /*
6082 * Sets the icon used for a given window. 6223 * Sets the icon used for a given window.
6343 6484
6344 if(!osName[0]) 6485 if(!osName[0])
6345 { 6486 {
6346 JNIEnv *jenv; 6487 JNIEnv *jenv;
6347 const char *release = nullptr; 6488 const char *release = nullptr;
6489 jstring jstr = nullptr;
6348 6490
6349 if((jenv = (JNIEnv *)pthread_getspecific(_dw_env_key))) 6491 if((jenv = (JNIEnv *)pthread_getspecific(_dw_env_key)))
6350 { 6492 {
6351 // First get the class that contains the method you need to call 6493 // First get the class that contains the method you need to call
6352 jclass clazz = _dw_find_class(jenv, DW_CLASS_NAME); 6494 jclass clazz = _dw_find_class(jenv, DW_CLASS_NAME);
6353 // Get the method that you want to call 6495 // Get the method that you want to call
6354 jmethodID androidGetRelease = jenv->GetMethodID(clazz, "androidGetRelease", 6496 jmethodID androidGetRelease = jenv->GetMethodID(clazz, "androidGetRelease",
6355 "()Ljava/lang/String;"); 6497 "()Ljava/lang/String;");
6356 // Call the method on the object 6498 // Call the method on the object
6357 jstring jstr = (jstring)_dw_jni_check_result(jenv, jenv->CallObjectMethod(_dw_obj, androidGetRelease), _DW_REFERENCE_NONE); 6499 jstr = (jstring)_dw_jni_check_result(jenv, jenv->CallObjectMethod(_dw_obj, androidGetRelease), _DW_REFERENCE_NONE);
6358 6500
6359 if(jstr) 6501 if(jstr)
6360 release = jenv->GetStringUTFChars(jstr, nullptr); 6502 release = jenv->GetStringUTFChars(jstr, nullptr);
6361 } 6503 }
6362 snprintf(osName, _DW_ENV_STRING_SIZE-1, "Android%s%s", 6504 snprintf(osName, _DW_ENV_STRING_SIZE-1, "Android%s%s",
6363 release ? " " : "", release ? release : ""); 6505 release ? " " : "", release ? release : "");
6506 if(release)
6507 jenv->ReleaseStringUTFChars(jstr, release);
6364 } 6508 }
6365 memset(env, '\0', sizeof(DWEnv)); 6509 memset(env, '\0', sizeof(DWEnv));
6366 6510
6367 strncpy(env->osName, osName, sizeof(env->osName)-1); 6511 strncpy(env->osName, osName, sizeof(env->osName)-1);
6368 strncpy(env->buildDate, __DATE__, sizeof(env->buildDate)-1); 6512 strncpy(env->buildDate, __DATE__, sizeof(env->buildDate)-1);
6428 jmethodID windowSetData = env->GetMethodID(clazz, "windowSetData", 6572 jmethodID windowSetData = env->GetMethodID(clazz, "windowSetData",
6429 "(Landroid/view/View;Ljava/lang/String;J)V"); 6573 "(Landroid/view/View;Ljava/lang/String;J)V");
6430 // Call the method on the object 6574 // Call the method on the object
6431 env->CallVoidMethod(_dw_obj, windowSetData, window, jstr, (jlong)data); 6575 env->CallVoidMethod(_dw_obj, windowSetData, window, jstr, (jlong)data);
6432 _dw_jni_check_exception(env); 6576 _dw_jni_check_exception(env);
6577 env->DeleteLocalRef(jstr);
6433 } 6578 }
6434 } 6579 }
6435 6580
6436 /* 6581 /*
6437 * Gets a named user data item from a window handle. 6582 * Gets a named user data item from a window handle.
6457 "(Landroid/view/View;Ljava/lang/String;)J"); 6602 "(Landroid/view/View;Ljava/lang/String;)J");
6458 // Call the method on the object 6603 // Call the method on the object
6459 retval = (void *)env->CallLongMethod(_dw_obj, windowGetData, window, jstr); 6604 retval = (void *)env->CallLongMethod(_dw_obj, windowGetData, window, jstr);
6460 if(_dw_jni_check_exception(env)) 6605 if(_dw_jni_check_exception(env))
6461 retval = nullptr; 6606 retval = nullptr;
6607 env->DeleteLocalRef(jstr);
6462 } 6608 }
6463 return retval; 6609 return retval;
6464 } 6610 }
6465 6611
6466 /* 6612 /*
7569 "(Ljava/lang/String;Ljava/lang/String;)I"); 7715 "(Ljava/lang/String;Ljava/lang/String;)I");
7570 // Call the method on the object 7716 // Call the method on the object
7571 _dw_android_api = env->CallIntMethod(_dw_obj, dwInit, appid, appname); 7717 _dw_android_api = env->CallIntMethod(_dw_obj, dwInit, appid, appname);
7572 if(_dw_jni_check_exception(env)) 7718 if(_dw_jni_check_exception(env))
7573 _dw_android_api = 0; 7719 _dw_android_api = 0;
7720 env->DeleteLocalRef(appid);
7721 env->DeleteLocalRef(appname);
7574 } 7722 }
7575 return DW_ERROR_NONE; 7723 return DW_ERROR_NONE;
7576 } 7724 }
7577 7725
7578 /* 7726 /*
7672 "(Ljava/lang/String;)I"); 7820 "(Ljava/lang/String;)I");
7673 // Call the method on the object 7821 // Call the method on the object
7674 retval = env->CallIntMethod(_dw_obj, browseURL, jstr); 7822 retval = env->CallIntMethod(_dw_obj, browseURL, jstr);
7675 if(_dw_jni_check_exception(env)) 7823 if(_dw_jni_check_exception(env))
7676 retval = DW_ERROR_UNKNOWN; 7824 retval = DW_ERROR_UNKNOWN;
7825 env->DeleteLocalRef(jstr);
7677 } 7826 }
7678 return retval; 7827 return retval;
7679 } 7828 }
7680 7829
7681 /* 7830 /*
7733 "(JILjava/lang/String;II)Landroid/print/PrintJob;"); 7882 "(JILjava/lang/String;II)Landroid/print/PrintJob;");
7734 // Call the method on the object 7883 // Call the method on the object
7735 print->printjob = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, printRun, (jlong)pr, (jint)print->flags, jstr, (jint)print->pages, (jint)flags), _DW_REFERENCE_WEAK); 7884 print->printjob = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, printRun, (jlong)pr, (jint)print->flags, jstr, (jint)print->pages, (jint)flags), _DW_REFERENCE_WEAK);
7736 if(print->printjob) 7885 if(print->printjob)
7737 retval = DW_ERROR_NONE; 7886 retval = DW_ERROR_NONE;
7887 env->DeleteLocalRef(jstr);
7738 } 7888 }
7739 return retval; 7889 return retval;
7740 } 7890 }
7741 7891
7742 /* 7892 /*
7813 // Get the method that you want to call 7963 // Get the method that you want to call
7814 jmethodID notificationNew = env->GetMethodID(clazz, "notificationNew", 7964 jmethodID notificationNew = env->GetMethodID(clazz, "notificationNew",
7815 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroidx/core/app/NotificationCompat$Builder;"); 7965 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroidx/core/app/NotificationCompat$Builder;");
7816 // Call the method on the object 7966 // Call the method on the object
7817 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, notificationNew, ntitle, image, ndesc, appid), _DW_REFERENCE_WEAK); 7967 jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, notificationNew, ntitle, image, ndesc, appid), _DW_REFERENCE_WEAK);
7968 env->DeleteLocalRef(appid);
7969 env->DeleteLocalRef(ntitle);
7818 return result; 7970 return result;
7819 } 7971 }
7820 return nullptr; 7972 return nullptr;
7821 } 7973 }
7822 7974