}
/* Given a Lisp string TEXT, return a local reference to an equivalent
- Java string. */
+ Java string. Each argument following TEXT should be NULL or a
+ local reference that will be freed if creating the string fails,
+ whereupon memory_full will also be signaled. */
jstring
-android_build_string (Lisp_Object text)
+android_build_string (Lisp_Object text, ...)
{
Lisp_Object encoded;
jstring string;
size_t nchars;
jchar *characters;
+ va_list ap;
+ jobject object;
+
USE_SAFE_ALLOCA;
/* Directly encode TEXT if it contains no non-ASCII characters, or
{
string = (*android_java_env)->NewStringUTF (android_java_env,
SSDATA (text));
- android_exception_check ();
- SAFE_FREE ();
+ if ((*android_java_env)->ExceptionCheck (android_java_env))
+ goto error;
+
+ SAFE_FREE ();
return string;
}
string
= (*android_java_env)->NewString (android_java_env,
characters, nchars);
- android_exception_check ();
+
+ if ((*android_java_env)->ExceptionCheck (android_java_env))
+ goto error;
SAFE_FREE ();
return string;
+
+ error:
+ /* An exception arose while creating the string. When this
+ transpires, an assumption is made that the error was induced by
+ running out of memory. Delete each of the local references
+ within AP. */
+
+ va_start (ap, text);
+
+ __android_log_print (ANDROID_LOG_WARN, __func__,
+ "Possible out of memory error. "
+ " The Java exception follows: ");
+ /* Describe exactly what went wrong. */
+ (*android_java_env)->ExceptionDescribe (android_java_env);
+ (*android_java_env)->ExceptionClear (android_java_env);
+
+ /* Now remove each and every local reference provided after
+ OBJECT. */
+
+ while ((object = va_arg (ap, jobject)))
+ ANDROID_DELETE_LOCAL_REF (object);
+
+ va_end (ap);
+ memory_full (0);
}
/* Do the same, except TEXT is constant string data in ASCII or
Lisp_Object tem;
const char *buffer;
- string = android_build_string (url);
+ string = android_build_string (url, NULL);
value
= (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
emacs_service,
extern void android_set_dont_accept_focus (android_window, bool);
extern int android_verify_jni_string (const char *);
-extern jstring android_build_string (Lisp_Object);
+extern jstring android_build_string (Lisp_Object, ...);
extern jstring android_build_jstring (const char *);
extern void android_exception_check (void);
extern void android_exception_check_1 (jobject);
title_string = NULL;
if (STRINGP (title) && menu_items_n_panes < 2)
- title_string = android_build_string (title);
+ title_string = android_build_string (title, NULL);
/* Push the first local frame for the context menu. */
method = menu_class.create_context_menu;
pane_name = Fsubstring (pane_name, make_fixnum (1), Qnil);
/* Add the pane. */
- temp = android_build_string (pane_name);
+ temp = android_build_string (pane_name, NULL);
android_exception_check ();
(*env)->CallNonvirtualVoidMethod (env, current_context_menu,
{
/* This is a submenu. Add it. */
title_string = (!NILP (item_name)
- ? android_build_string (item_name)
+ ? android_build_string (item_name, NULL)
: NULL);
help_string = NULL;
if (android_get_current_api_level () >= 26
&& STRINGP (help))
- help_string = android_build_string (help);
+ help_string = android_build_string (help, NULL);
store = current_context_menu;
current_context_menu
/* Add this menu item with the appropriate state. */
title_string = (!NILP (item_name)
- ? android_build_string (item_name)
+ ? android_build_string (item_name, NULL)
: NULL);
help_string = NULL;
if (android_get_current_api_level () >= 26
&& STRINGP (help))
- help_string = android_build_string (help);
+ help_string = android_build_string (help, NULL);
/* Determine whether or not to display a check box. */
: android_build_jstring ("Question"));
/* And the title. */
- java_title = android_build_string (title);
+ java_title = android_build_string (title, NULL);
/* Now create the dialog. */
method = dialog_class.create_dialog;
}
/* Add the button. */
- temp = android_build_string (item_name);
+ temp = android_build_string (item_name, NULL);
(*env)->CallNonvirtualVoidMethod (env, dialog,
dialog_class.class,
dialog_class.add_button,
(long int) (boot_time.tv_sec / 2), id);
/* Encode all strings into their Java counterparts. */
- title1 = android_build_string (title);
- body1 = android_build_string (body);
- group1 = android_build_string (group);
- identifier1 = android_build_jstring (identifier);
+ title1 = android_build_string (title, NULL);
+ body1 = android_build_string (body, title1, NULL);
+ group1 = android_build_string (group, body1, title1, NULL);
+ identifier1
+ = (*android_java_env)->NewStringUTF (android_java_env, identifier);
+ android_exception_check_3 (title1, body1, group1);
/* Create the notification. */
notification
/* First, check for an exception. */
if (!(*env)->ExceptionCheck (env))
- /* No exception has taken place. Return 0. */
- return 0;
+ {
+ /* No exception has taken place. Return 0. */
+ va_end (ap);
+ return 0;
+ }
/* Print the exception. */
(*env)->ExceptionDescribe (env);
/* expression is still a local reference! */
ANDROID_DELETE_LOCAL_REF ((jobject) exception);
errno = new_errno;
+ va_end (ap);
return 1;
}