summaryrefslogtreecommitdiff
path: root/demos
diff options
context:
space:
mode:
Diffstat (limited to 'demos')
-rw-r--r--demos/c/Makefile12
-rw-r--r--demos/c/api_test.c31
-rw-r--r--demos/csharp/api/ghostapi.cs109
-rw-r--r--demos/csharp/api/ghostnet.cs497
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/DocPage.cs10
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/MainPrint.cs83
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/MainRender.cs158
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/MainThumbRendering.cs23
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/MainWindow.xaml.cs164
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/MainZoom.cs47
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml21
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml.cs27
-rw-r--r--demos/csharp/windows/ghostnet_wpf_example/ghostnet_simple_viewer.csproj41
-rw-r--r--demos/java/gsjava/.classpath6
-rw-r--r--demos/java/gsjava/.project17
-rw-r--r--demos/java/gsjava/README.txt149
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/GSAPI.java284
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java320
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/DisplayCallback.java75
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/ICalloutFunction.java7
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/IPollFunction.java7
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdErrFunction.java15
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdInFunction.java15
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdOutFunction.java16
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/BMPDevice.java18
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/Device.java308
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceInUseException.java17
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceNotSupportedException.java28
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/DisplayDevice.java55
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/EPSDevice.java9
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/FAXDevice.java18
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/FileDevice.java36
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/HighLevelDevice.java13
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/JPEGDevice.java19
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/OCRDevice.java24
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PCXDevice.java17
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PDFDevice.java90
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PDFImageDevice.java19
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PDFPostscriptDeviceFamily.java340
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PNGDevice.java36
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PNMDevice.java25
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PSDDevice.java17
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PXLDevice.java17
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/PostScriptDevice.java59
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/TIFFDevice.java80
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/TextDevice.java14
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/devices/XPSDevice.java9
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/AllocationError.java33
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/ByteArrayReference.java23
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/BytePointer.java68
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/NativeArray.java67
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/NativePointer.java157
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java45
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/StringUtil.java41
-rw-r--r--demos/java/gstest/.classpath7
-rw-r--r--demos/java/gstest/.project17
-rw-r--r--demos/java/gstest/src/gstest/Main.java41
-rw-r--r--demos/java/gsviewer/.classpath7
-rw-r--r--demos/java/gsviewer/.project17
-rw-r--r--demos/java/gsviewer/README.txt4
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/DefaultUnhandledExceptionHandler.java107
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Document.java1075
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/GSFileFilter.java50
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/ImageUtil.java45
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Main.java42
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/PDFFileFilter.java28
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Page.java359
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/PageUpdateCallback.java15
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Settings.java142
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/StdIO.java38
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/ViewerController.java372
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/gui/ScrollMap.java142
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/gui/SettingsDialog.java241
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerGUIListener.java61
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerWindow.java1020
-rw-r--r--demos/java/jni/gs_jni/callbacks.cpp368
-rw-r--r--demos/java/jni/gs_jni/callbacks.h54
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp555
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h386
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.cpp131
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h169
-rw-r--r--demos/java/jni/gs_jni/dllmain.cpp19
-rw-r--r--demos/java/jni/gs_jni/framework.h5
-rw-r--r--demos/java/jni/gs_jni/gs_jni.sln31
-rw-r--r--demos/java/jni/gs_jni/gs_jni.vcxproj184
-rw-r--r--demos/java/jni/gs_jni/gs_jni.vcxproj.filters51
-rw-r--r--demos/java/jni/gs_jni/include/classfile_constants.h560
-rw-r--r--demos/java/jni/gs_jni/include/jawt.h299
-rw-r--r--demos/java/jni/gs_jni/include/jdwpTransport.h259
-rw-r--r--demos/java/jni/gs_jni/include/jni.h1964
-rw-r--r--demos/java/jni/gs_jni/include/jvmti.h2533
-rw-r--r--demos/java/jni/gs_jni/include/jvmticmlr.h115
-rw-r--r--demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCallbacks.h96
-rw-r--r--demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.c1131
-rw-r--r--demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.h706
-rw-r--r--demos/java/jni/gs_jni/include/win32/bridge/AccessBridgePackages.h2215
-rw-r--r--demos/java/jni/gs_jni/include/win32/jawt_md.h59
-rw-r--r--demos/java/jni/gs_jni/include/win32/jni_md.h37
-rw-r--r--demos/java/jni/gs_jni/jni_util.cpp593
-rw-r--r--demos/java/jni/gs_jni/jni_util.h377
-rwxr-xr-xdemos/python/gsapiwrap.py699
-rw-r--r--demos/python/jlib.py1355
102 files changed, 20269 insertions, 2348 deletions
diff --git a/demos/c/Makefile b/demos/c/Makefile
new file mode 100644
index 00000000..63dc4da5
--- /dev/null
+++ b/demos/c/Makefile
@@ -0,0 +1,12 @@
+api_test: api_test.c
+ (cd ../.. && ./autogen.sh)
+ (cd ../.. && make so XCFLAGS="-DCLUSTER")
+ pwd
+ gcc -fPIC -I../.. api_test.c -DGHOSTPDL=1 -lgpdl -L../../sobin -o api_test
+
+run_api_test: api_test
+ LD_LIBRARY_PATH=../../sobin ./api_test
+
+post_api_test:
+ md5sum apitest*
+ rm apitest*
diff --git a/demos/c/api_test.c b/demos/c/api_test.c
index 8cc61e78..2768c6bf 100644
--- a/demos/c/api_test.c
+++ b/demos/c/api_test.c
@@ -5,6 +5,11 @@
#define _WINDOWS_
#endif
+/* We can't have pointers displayed in the test output, as that will
+ * change the output between runs. The following definition hides
+ * them. */
+#define HIDE_POINTERS
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,6 +17,7 @@
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
+#include <stdint.h>
#ifndef GHOSTPDL
#define GHOSTPDL 1
@@ -72,6 +78,21 @@ typedef struct {
const char *fname;
} teststate_t;
+#ifdef HIDE_POINTERS
+void *hide_pointer(void *p)
+{
+ return (p == NULL) ? NULL : (void *)1;
+}
+
+#define PTR(p) hide_pointer(p)
+
+#else
+
+#define PTR(p) p
+
+#endif
+
+
/*--------------------------------------------------------------------*/
/* First off, we have a set of functions that cope with dumping lines
* of rendered data to file. We use pnm formats for their simplicity. */
@@ -336,7 +357,7 @@ size(void *handle, void *device, int width, int height,
SANITY_CHECK(ts);
printf("size: w=%d h=%d r=%d f=%x m=%p\n",
- width, height, raster, format, pimage);
+ width, height, raster, format, PTR(pimage));
ts->w = width;
ts->h = height;
ts->r = raster;
@@ -429,7 +450,7 @@ memalloc(void *handle, void *device, size_t size)
}
ret = aligned_malloc(size, 64);
- printf("memalloc: %"FMT_Z" -> %p\n", Z_CAST size, ret);
+ printf("memalloc: %"FMT_Z" -> %p\n", Z_CAST size, PTR(ret));
return ret;
}
@@ -440,7 +461,7 @@ memfree(void *handle, void *device, void *mem)
teststate_t *ts = (teststate_t *)handle;
SANITY_CHECK(ts);
- printf("memfree: %p\n", mem);
+ printf("memfree: %p\n", PTR(mem));
aligned_free(mem);
return 0;
@@ -553,7 +574,7 @@ rectangle_request(void *handle, void *device,
ts->mem = aligned_malloc(size, 64);
*memory = ts->mem;
- printf("x=%d y=%d w=%d h=%d mem=%p\n", *x, *y, *w, *h, *memory);
+ printf("x=%d y=%d w=%d h=%d mem=%p\n", *x, *y, *w, *h, PTR(*memory));
if (ts->mem == NULL)
return -1;
@@ -882,7 +903,7 @@ static int
list_params(void *instance)
{
void *iter = NULL;
- char *key;
+ const char *key;
gs_set_param_type type;
char buffer[1024];
int code;
diff --git a/demos/csharp/api/ghostapi.cs b/demos/csharp/api/ghostapi.cs
index b65aac9e..a3491fd7 100644
--- a/demos/csharp/api/ghostapi.cs
+++ b/demos/csharp/api/ghostapi.cs
@@ -22,7 +22,9 @@ namespace GhostAPI
gs_spt_string = 5, /* void * is a char * */
gs_spt_long = 6, /* void * is a long * */
gs_spt_i64 = 7, /* void * is a int64_t * */
- gs_spt_size_t = 8 /* void * is a size_t * */
+ gs_spt_size_t = 8, /* void * is a size_t * */
+ gs_spt_parsed = 9, /* void * is a pointer to a char * to be parsed */
+ gs_spt_more_to_come = 1 << 31
};
public enum gsEncoding
@@ -63,7 +65,7 @@ namespace GhostAPI
#endif
#endif
/* Callback proto for stdio */
- public delegate int gsStdIOHandler(IntPtr caller_handle, IntPtr buffer, int len);
+ public delegate int gs_stdio_handler(IntPtr caller_handle, IntPtr buffer, int len);
/* Callback proto for poll function */
public delegate int gsPollHandler(IntPtr caller_handle);
@@ -84,38 +86,43 @@ namespace GhostAPI
CallingConvention = CallingConvention.StdCall)]
public static extern void gsapi_delete_instance(IntPtr instance);
- [DllImport(lib_dll, EntryPoint = "gsapi_init_with_args", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_init_with_args(IntPtr instance, int argc,
- IntPtr argv);
-
- [DllImport(lib_dll, EntryPoint = "gsapi_exit", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_exit(IntPtr instance);
-
- [DllImport(lib_dll, EntryPoint = "gsapi_set_arg_encoding", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_set_stdio_with_handle", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_set_arg_encoding(IntPtr instance,
- int encoding);
+ public static extern int gsapi_set_stdio_with_handle(IntPtr instance,
+ gs_stdio_handler stdin, gs_stdio_handler stdout, gs_stdio_handler stderr, IntPtr caller_handle);
[DllImport(lib_dll, EntryPoint = "gsapi_set_stdio", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern int gsapi_set_stdio(IntPtr instance,
- gsStdIOHandler stdin, gsStdIOHandler stdout, gsStdIOHandler stderr);
+ gs_stdio_handler stdin, gs_stdio_handler stdout, gs_stdio_handler stderr);
- [DllImport(lib_dll, EntryPoint = "gsapi_set_stdio_with_handle", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_set_poll_with_handle", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_set_stdio_with_handle(IntPtr instance,
- gsStdIOHandler stdin, gsStdIOHandler stdout, gsStdIOHandler stderr, IntPtr caller_handle);
+ public static extern int gsapi_set_poll_with_handle(IntPtr instance, gsPollHandler pollfn,
+ IntPtr caller_handle);
[DllImport(lib_dll, EntryPoint = "gsapi_set_poll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern int gsapi_set_poll(IntPtr instance, gsPollHandler pollfn);
- [DllImport(lib_dll, EntryPoint = "gsapi_set_poll_with_handle", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_set_display_callback", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_set_poll_with_handle(IntPtr instance, gsPollHandler pollfn,
- IntPtr caller_handle);
+ public static extern int gsapi_set_display_callback(IntPtr pinstance, IntPtr caller_handle);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_register_callout", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_register_callout(IntPtr instance, gsCallOut callout,
+ IntPtr callout_handle);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_deregister_callout", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_deregister_callout(IntPtr instance, gsCallOut callout,
+ IntPtr callout_handle);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_set_arg_encoding", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_set_arg_encoding(IntPtr instance,
+ int encoding);
[DllImport(lib_dll, EntryPoint = "gsapi_get_default_device_list", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
@@ -127,9 +134,19 @@ namespace GhostAPI
public static extern int gsapi_set_default_device_list(IntPtr instance,
IntPtr list, ref int listlen);
- [DllImport(lib_dll, EntryPoint = "gsapi_run_string", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_run_string_begin", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_run_string(IntPtr instance, IntPtr command,
+ public static extern int gsapi_run_string_begin(IntPtr instance,
+ int usererr, ref int exitcode);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_run_string_continue", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_run_string_continue(IntPtr instance,
+ IntPtr command, int count, int usererr, ref int exitcode);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_run_string_end", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_run_string_end(IntPtr instance,
int usererr, ref int exitcode);
[DllImport(lib_dll, EntryPoint = "gsapi_run_string_with_length", CharSet = CharSet.Ansi,
@@ -137,29 +154,39 @@ namespace GhostAPI
public static extern int gsapi_run_string_with_length(IntPtr instance, IntPtr command,
uint length, int usererr, ref int exitcode);
+ [DllImport(lib_dll, EntryPoint = "gsapi_run_string", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_run_string(IntPtr instance, IntPtr command,
+ int usererr, ref int exitcode);
+
[DllImport(lib_dll, EntryPoint = "gsapi_run_file", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern int gsapi_run_file(IntPtr instance, IntPtr filename,
int usererr, ref int exitcode);
- [DllImport(lib_dll, EntryPoint = "gsapi_run_string_begin", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_init_with_args", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_run_string_begin(IntPtr instance,
- int usererr, ref int exitcode);
+ public static extern int gsapi_init_with_args(IntPtr instance, int argc,
+ IntPtr argv);
- [DllImport(lib_dll, EntryPoint = "gsapi_run_string_continue", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_run_string_continue(IntPtr instance,
- IntPtr command, int count, int usererr, ref int exitcode);
+ [DllImport(lib_dll, EntryPoint = "gsapi_exit", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_exit(IntPtr instance);
- [DllImport(lib_dll, EntryPoint = "gsapi_run_string_end", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_set_param", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_run_string_end(IntPtr instance,
- int usererr, ref int exitcode);
+ public static extern int gsapi_set_param(IntPtr instance, IntPtr param, IntPtr value,
+ gs_set_param_type type);
- [DllImport(lib_dll, EntryPoint = "gsapi_set_display_callback", CharSet = CharSet.Ansi,
+ [DllImport(lib_dll, EntryPoint = "gsapi_get_param", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_set_display_callback(IntPtr pinstance, IntPtr caller_handle);
+ public static extern int gsapi_get_param(IntPtr instance, IntPtr param, IntPtr value,
+ gs_set_param_type type);
+
+ [DllImport(lib_dll, EntryPoint = "gsapi_enumerate_params", CharSet = CharSet.Ansi,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int gsapi_enumerate_params(IntPtr instance, out IntPtr inter,
+ out IntPtr key, IntPtr type);
[DllImport(lib_dll, EntryPoint = "gsapi_add_control_path", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
@@ -181,19 +208,7 @@ namespace GhostAPI
CallingConvention = CallingConvention.StdCall)]
public static extern int gsapi_is_path_control_active(IntPtr instance);
- [DllImport(lib_dll, EntryPoint = "gsapi_set_param", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_set_param(IntPtr instance, gs_set_param_type type,
- IntPtr param, IntPtr value);
- [DllImport(lib_dll, EntryPoint = "gsapi_register_callout", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_register_callout(IntPtr instance, gsCallOut callout,
- IntPtr callout_handle);
- [DllImport(lib_dll, EntryPoint = "gsapi_deregister_callout", CharSet = CharSet.Ansi,
- CallingConvention = CallingConvention.StdCall)]
- public static extern int gsapi_deregister_callout(IntPtr instance, gsCallOut callout,
- IntPtr callout_handle);
}
}
diff --git a/demos/csharp/api/ghostnet.cs b/demos/csharp/api/ghostnet.cs
index 9011768e..f033941f 100644
--- a/demos/csharp/api/ghostnet.cs
+++ b/demos/csharp/api/ghostnet.cs
@@ -4,9 +4,7 @@ using System.ComponentModel; /* Background threading */
using System.Collections.Generic; /* Use of List */
using System.IO; /* Use of path */
using GhostAPI; /* Use of Ghostscript API */
-#if WPF
using ghostnet_wpf_example; /* For Print control */
-#endif
namespace GhostNET
{
@@ -17,10 +15,10 @@ namespace GhostNET
SAVE_RESULT,
GET_PAGE_COUNT,
GENERIC,
- DISPLAY_DEV_THUMBS_NON_PDF,
- DISPLAY_DEV_THUMBS_PDF,
+ DISPLAY_DEV_THUMBS,
DISPLAY_DEV_NON_PDF,
DISPLAY_DEV_PDF,
+ DISPLAY_DEV_RUN_FILE
}
public enum GS_Result_t
{
@@ -50,6 +48,8 @@ namespace GhostNET
public List<String> args;
public int return_code;
public double zoom;
+ public bool aa;
+ public bool is_valid;
};
public class gsEventArgs : EventArgs
@@ -86,37 +86,46 @@ public class gsEventArgs : EventArgs
}
}
- /* Ghostscript display device callback delegates. */
+ /* Ghostscript display device callback delegates. Make sure that
+ these are using Cdecl calling convention, which means gsdll
+ is doing the stack cleanup after the call */
/* New device has been opened */
/* This is the first event from this device. */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_open_del(IntPtr handle, IntPtr device);
/* Device is about to be closed. */
/* Device will not be closed until this function returns. */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_preclose_del(IntPtr handle, IntPtr device);
/* Device has been closed. */
/* This is the last event from this device. */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_close_del(IntPtr handle, IntPtr device);
/* Device is about to be resized. */
/* Resize will only occur if this function returns 0. */
/* raster is byte count of a row. */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_presize_del(IntPtr handle, IntPtr device,
int width, int height, int raster, uint format);
/* Device has been resized. */
/* New pointer to raster returned in pimage */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_size_del(IntPtr handle, IntPtr device,
int width, int height, int raster, uint format,
IntPtr pimage);
/* flushpage */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_sync_del(IntPtr handle, IntPtr device);
/* showpage */
/* If you want to pause on showpage, then don't return immediately */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_page_del(IntPtr handle, IntPtr device, int copies, int flush);
@@ -125,6 +134,7 @@ public class gsEventArgs : EventArgs
* progressive update of the display.
* This function pointer may be set to NULL if not required.
*/
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_update_del(IntPtr handle, IntPtr device, int x, int y,
int w, int h);
@@ -135,10 +145,12 @@ public class gsEventArgs : EventArgs
* image buffer. The first row will be placed at the address
* returned by display_memalloc.
*/
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_memalloc_del(IntPtr handle, IntPtr device, ulong size);
/* Free memory for bitmap */
/* If this is NULL, the Ghostscript memory device will free the bitmap */
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int display_memfree_del(IntPtr handle, IntPtr device, IntPtr mem);
private int display_size(IntPtr handle, IntPtr device,
@@ -200,10 +212,6 @@ public class gsEventArgs : EventArgs
return 0;
}
- /* Delegate for stdio */
- public delegate int gs_stdio_handler(IntPtr caller_handle, IntPtr buffer,
- int len);
-
private int stdin_callback(IntPtr handle, IntPtr pointer, int count)
{
String output = Marshal.PtrToStringAnsi(pointer);
@@ -231,7 +239,50 @@ public class gsEventArgs : EventArgs
var mess = excep2.Message;
}
- return count;
+ /* Callback for progress on XPS creation */
+ if (m_params.task == GS_Task_t.CREATE_XPS)
+ {
+ /* See if we have a page number */
+ if (count >= 7 && output.Substring(0, 4) == "Page")
+ {
+ String page = output.Substring(5, count - 6);
+ int numVal;
+ try
+ {
+ double perc = 0.0;
+ numVal = System.Convert.ToInt32(page);
+ if (m_params.firstpage == -1 && m_params.lastpage == -1 &&
+ m_params.pages == null)
+ {
+ /* Doing full document */
+ perc = 100.0 * (double)numVal / (double)m_params.num_pages;
+ }
+ else
+ {
+ if (m_params.pages != null)
+ {
+ perc = 100.0 * ((double)numVal - m_params.currpage) / (double)m_params.num_pages;
+ m_params.currpage = m_params.currpage + 1;
+ }
+ else
+ {
+ /* continugous set of pages */
+ perc = 100.0 * ((double)numVal - m_params.firstpage + 1) / (double)m_params.num_pages;
+ }
+ }
+ m_worker.ReportProgress((int)perc, m_params);
+ }
+ catch (FormatException)
+ {
+ Console.WriteLine("XPSPrint Error: Input string is not a sequence of digits.");
+ }
+ catch (OverflowException)
+ {
+ Console.WriteLine("XPSPrint Error: The number cannot fit in an Int32.");
+ }
+ }
+ }
+ return count;
}
private int stderr_callback(IntPtr handle, IntPtr pointer, int count)
@@ -249,6 +300,8 @@ public class gsEventArgs : EventArgs
int m_pagewidth;
int m_pageheight;
int m_pageraster;
+ gsParamState_t m_displaystate;
+
display_callback_t m_display_callback;
IntPtr ptr_display_struct;
@@ -267,13 +320,15 @@ public class gsEventArgs : EventArgs
IntPtr data, gsParamState_t state);
internal event gsCallBackPageRenderedMain gsPageRenderedMain;
-
+
/* From my understanding you cannot pin delegates. These need to be declared
* as members to keep a reference to the delegates and avoid their possible GC.
- * since the C# GC has no idea that GS has a reference to these items. */
- readonly gs_stdio_handler raise_stdin;
- readonly gs_stdio_handler raise_stdout;
- readonly gs_stdio_handler raise_stderr;
+ * since the C# GC has no idea that GS has a reference to these items. While the
+ * methods themselves dont move, apparently the address of the translation code
+ * is what is passed, and one of these abstractions can be GC or relocated. */
+ ghostapi.gs_stdio_handler raise_stdin;
+ ghostapi.gs_stdio_handler raise_stdout;
+ ghostapi.gs_stdio_handler raise_stderr;
/* Ghostscript display callback struct */
public struct display_callback_t
@@ -298,6 +353,10 @@ public class gsEventArgs : EventArgs
gsInstance = IntPtr.Zero;
dispInstance = IntPtr.Zero;
+ /* To keep track if we need to update any parameters */
+ m_displaystate = new gsParamState_t();
+ m_displaystate.is_valid = false;
+
/* Avoiding delegate GC during the life of this object */
raise_stdin = stdin_callback;
raise_stdout = stdout_callback;
@@ -371,10 +430,12 @@ public class gsEventArgs : EventArgs
break;
case GS_Task_t.DISPLAY_DEV_NON_PDF:
case GS_Task_t.DISPLAY_DEV_PDF:
- case GS_Task_t.DISPLAY_DEV_THUMBS_NON_PDF:
- case GS_Task_t.DISPLAY_DEV_THUMBS_PDF:
+ case GS_Task_t.DISPLAY_DEV_THUMBS:
m_worker.DoWork -= new DoWorkEventHandler(DisplayDeviceAsync);
break;
+ case GS_Task_t.DISPLAY_DEV_RUN_FILE:
+ m_worker.DoWork -= new DoWorkEventHandler(DisplayDeviceRun);
+ break;
default:
m_worker.DoWork -= new DoWorkEventHandler(gsFileAsync);
break;
@@ -398,8 +459,7 @@ public class gsEventArgs : EventArgs
private void gsProgressChanged(object sender, ProgressChangedEventArgs e)
{
/* Callback with progress */
- gsParamState_t Value = new gsParamState_t();
- gsEventArgs info = new gsEventArgs(false, e.ProgressPercentage, Value);
+ gsEventArgs info = new gsEventArgs(false, e.ProgressPercentage, (gsParamState_t) e.UserState);
gsUpdateMain(info);
}
private gsParamState_t gsFileSync(gsParamState_t in_params)
@@ -706,7 +766,7 @@ public class gsEventArgs : EventArgs
total = total + count;
perc = 100.0 * (double)total / (double)len;
- worker.ReportProgress((int)perc);
+ worker.ReportProgress((int)perc, Params);
if (worker.CancellationPending == true)
{
e.Cancel = true;
@@ -785,46 +845,245 @@ public class gsEventArgs : EventArgs
return;
}
- /* Worker task for using display device */
- private void DisplayDeviceAsync(object sender, DoWorkEventArgs e)
+ private void SetPageRange(int first, int last, bool delay)
+ {
+ int code;
+
+ byte[] param_first = System.Text.Encoding.UTF8.GetBytes("FirstPage" + "\0");
+ byte[] param_last = System.Text.Encoding.UTF8.GetBytes("LastPage" + "\0");
+
+ GCHandle pinParamFirst = GCHandle.Alloc(param_first, GCHandleType.Pinned);
+ GCHandle pinParamLast = GCHandle.Alloc(param_last, GCHandleType.Pinned);
+ GCHandle firstValue = GCHandle.Alloc(first, GCHandleType.Pinned);
+ GCHandle lastValue = GCHandle.Alloc(last, GCHandleType.Pinned);
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamFirst.AddrOfPinnedObject(),
+ firstValue.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int | gs_set_param_type.gs_spt_more_to_come);
+ if (code < 0)
+ {
+ pinParamFirst.Free();
+ pinParamLast.Free();
+ firstValue.Free();
+ lastValue.Free();
+ throw new GhostscriptException("SetPageRange: gsapi_set_param error");
+ }
+
+ if (delay)
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamLast.AddrOfPinnedObject(),
+ lastValue.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int | gs_set_param_type.gs_spt_more_to_come);
+ else
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamLast.AddrOfPinnedObject(),
+ lastValue.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int);
+
+ pinParamFirst.Free();
+ pinParamLast.Free();
+ firstValue.Free();
+ lastValue.Free();
+
+ if (code < 0)
+ {
+ throw new GhostscriptException("SetPageRange: gsapi_set_param error");
+ }
+ }
+
+ private void SetAA(bool aa, bool delay)
+ {
+ int code;
+ int value;
+ byte[] param_text = System.Text.Encoding.UTF8.GetBytes("TextAlphaBits" + "\0");
+ byte[] param_graph = System.Text.Encoding.UTF8.GetBytes("GraphicsAlphaBits" + "\0");
+
+ if (aa)
+ value = 4;
+ else
+ value = 1;
+
+ GCHandle pinParamText = GCHandle.Alloc(param_text, GCHandleType.Pinned);
+ GCHandle pinParamGraph = GCHandle.Alloc(param_graph, GCHandleType.Pinned);
+ GCHandle valueParam = GCHandle.Alloc(value, GCHandleType.Pinned);
+
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamText.AddrOfPinnedObject(),
+ valueParam.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int | gs_set_param_type.gs_spt_more_to_come);
+ if (code < 0)
+ {
+ pinParamText.Free();
+ pinParamGraph.Free();
+ valueParam.Free();
+ throw new GhostscriptException("SetAA: gsapi_set_param error");
+ }
+ if (delay)
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamGraph.AddrOfPinnedObject(),
+ valueParam.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int | gs_set_param_type.gs_spt_more_to_come);
+ else
+ code = ghostapi.gsapi_set_param(dispInstance, pinParamGraph.AddrOfPinnedObject(),
+ valueParam.AddrOfPinnedObject(), gs_set_param_type.gs_spt_int);
+
+ pinParamText.Free();
+ pinParamGraph.Free();
+ valueParam.Free();
+
+ if (code < 0)
+ {
+ throw new GhostscriptException("SetAA: gsapi_set_param error");
+ }
+ }
+
+ private void SetResolution(double zoom, bool delay)
+ {
+ int resolution = (int)(72.0 * zoom + 0.5);
+ int code;
+
+ byte[] param = System.Text.Encoding.UTF8.GetBytes("HWResolution" + "\0");
+ byte[] value = System.Text.Encoding.UTF8.GetBytes("[" + resolution + " " + resolution + "]\0");
+ GCHandle pinParam = GCHandle.Alloc(param, GCHandleType.Pinned);
+ GCHandle valueParam = GCHandle.Alloc(value, GCHandleType.Pinned);
+
+ if (delay)
+ code = ghostapi.gsapi_set_param(dispInstance, pinParam.AddrOfPinnedObject(),
+ valueParam.AddrOfPinnedObject(), gs_set_param_type.gs_spt_parsed | gs_set_param_type.gs_spt_more_to_come);
+ else
+ code = ghostapi.gsapi_set_param(dispInstance, pinParam.AddrOfPinnedObject(),
+ valueParam.AddrOfPinnedObject(), gs_set_param_type.gs_spt_parsed);
+
+ pinParam.Free();
+ valueParam.Free();
+
+ if (code < 0)
+ {
+ throw new GhostscriptException("SetResolution: gsapi_set_param error");
+ }
+ }
+
+ /* Worker task for running a file with a page range, aa and zoom level */
+ private void DisplayDeviceRun(object sender, DoWorkEventArgs e)
{
int code = 0;
gsParamState_t gsparams = (gsParamState_t)e.Argument;
- GCHandle argPtrsStable = new GCHandle();
+ int exitcode = 0;
+ gsparams.result = GS_Result_t.gsOK;
- int num_params = gsparams.args.Count;
- var argParam = new GCHandle[num_params];
- var argPtrs = new IntPtr[num_params];
- List<byte[]> CharacterArray = new List<byte[]>(num_params);
- bool cleanup = true;
+ String fileName = gsparams.inputfile;
+ int firstpage = gsparams.firstpage;
+ int lastpage = gsparams.lastpage;
gsparams.result = GS_Result_t.gsOK;
+ if (dispInstance == IntPtr.Zero)
+ {
+ gsparams.result = GS_Result_t.gsFAILED;
+ e.Result = gsparams;
+ gsDLLProblemMain("Failure: Display device not initialized");
+ return;
+ }
+
try
{
- code = ghostapi.gsapi_new_instance(out dispInstance, IntPtr.Zero);
- if (code < 0)
+ /* Set parameters if needed */
+ if (!m_displaystate.is_valid)
{
- throw new GhostscriptException("DisplayDeviceAsync: gsapi_new_instance error");
- }
+ /* First time after thumbnails */
+ if (gsparams.aa)
+ {
+ SetAA(gsparams.aa, true);
+ }
- code = ghostapi.gsapi_set_stdio(dispInstance, stdin_callback, stdout_callback, stderr_callback);
- if (code < 0)
- {
- throw new GhostscriptException("DisplayDeviceAsync: gsapi_set_stdio error");
+ if (!(gsparams.firstpage == -1 && gsparams.lastpage == -1))
+ {
+ SetResolution(gsparams.zoom, true);
+ SetPageRange(gsparams.firstpage, gsparams.lastpage, false);
+ }
+ else
+ {
+ SetResolution(gsparams.zoom, false);
+ }
+ m_displaystate.is_valid = true;
}
-
- code = ghostapi.gsapi_set_arg_encoding(dispInstance, (int)gsEncoding.GS_ARG_ENCODING_UTF8);
- if (code < 0)
+ else
{
- throw new GhostscriptException("DisplayDeviceAsync: gsapi_set_arg_encoding error");
+ /* Rendering page range */
+ if (!(gsparams.firstpage == -1 && gsparams.lastpage == -1))
+ {
+ if (gsparams.aa != m_displaystate.aa)
+ SetAA(gsparams.aa, true);
+ if (gsparams.zoom != m_displaystate.zoom)
+ SetResolution(gsparams.zoom, true);
+ SetPageRange(gsparams.firstpage, gsparams.lastpage, false);
+ }
+ else
+ {
+ /* Rendering all pages */
+ if (gsparams.aa != m_displaystate.aa)
+ {
+ if (gsparams.zoom != m_displaystate.zoom)
+ {
+ /* Zoom and AA change */
+ SetAA(gsparams.aa, true);
+ SetResolution(gsparams.zoom, false);
+ }
+ else
+ {
+ /* AA change only */
+ SetAA(gsparams.aa, false);
+ }
+ }
+ else
+ {
+ if (gsparams.zoom != m_displaystate.zoom)
+ {
+ /* Zoom change only */
+ SetResolution(gsparams.zoom, false);
+ }
+ }
+ }
}
+ m_displaystate.aa = gsparams.aa;
+ m_displaystate.zoom = gsparams.zoom;
- code = ghostapi.gsapi_set_display_callback(dispInstance, ptr_display_struct);
- if (code < 0)
+ byte[] fname = System.Text.Encoding.UTF8.GetBytes(fileName + "\0");
+ GCHandle pinfname = GCHandle.Alloc(fname, GCHandleType.Pinned);
+ code = ghostapi.gsapi_run_file(dispInstance, pinfname.AddrOfPinnedObject(), 0, ref exitcode);
+ pinfname.Free();
+
+ if (exitcode < 0)
{
- throw new GhostscriptException("DisplayDeviceAsync: gsapi_set_display_callback error");
+ throw new GhostscriptException("DisplayDeviceRun: gsapi_run_file error");
}
+ }
+ catch (GhostscriptException except)
+ {
+ gsparams.result = GS_Result_t.gsFAILED;
+ gsDLLProblemMain("Exception: " + except.Message);
+ }
+ finally
+ {
+ e.Result = gsparams;
+ }
+ }
+
+ /* Worker task for using display device */
+ private void DisplayDeviceAsync(object sender, DoWorkEventArgs e)
+ {
+ int code = 0;
+ gsParamState_t gsparams = (gsParamState_t)e.Argument;
+ GCHandle argPtrsStable = new GCHandle();
+
+ int num_params = gsparams.args.Count;
+ var argParam = new GCHandle[num_params];
+ var argPtrs = new IntPtr[num_params];
+ List<byte[]> CharacterArray = new List<byte[]>(num_params);
+ bool cleanup = true;
+
+ gsparams.result = GS_Result_t.gsOK;
+
+ if (dispInstance == IntPtr.Zero)
+ {
+ gsparams.result = GS_Result_t.gsFAILED;
+ e.Result = gsparams;
+ gsDLLProblemMain("Failure: Display device not initialized");
+ return;
+ }
+
+ try
+ {
String fullcommand = "";
for (int k = 0; k < num_params; k++)
@@ -863,17 +1122,11 @@ public class gsEventArgs : EventArgs
{
gsDLLProblemMain("Exception: " + except.Message);
gsparams.result = GS_Result_t.gsFAILED;
- if (dispInstance != IntPtr.Zero)
- ghostapi.gsapi_delete_instance(dispInstance);
- dispInstance = IntPtr.Zero;
}
catch (Exception except)
{
gsDLLProblemMain("Exception: " + except.Message);
gsparams.result = GS_Result_t.gsFAILED;
- if (dispInstance != IntPtr.Zero)
- ghostapi.gsapi_delete_instance(dispInstance);
- dispInstance = IntPtr.Zero;
}
finally
{
@@ -885,16 +1138,6 @@ public class gsEventArgs : EventArgs
}
argPtrsStable.Free();
e.Result = gsparams;
-
- if (gsparams.result == GS_Result_t.gsOK && (gsparams.task == GS_Task_t.DISPLAY_DEV_NON_PDF ||
- gsparams.task == GS_Task_t.DISPLAY_DEV_THUMBS_NON_PDF))
- {
- gsParamState_t result = DisplayDeviceClose();
- if (gsparams.result == 0)
- {
- gsparams.result = result.result;
- }
- }
}
}
return;
@@ -927,10 +1170,12 @@ public class gsEventArgs : EventArgs
break;
case GS_Task_t.DISPLAY_DEV_NON_PDF:
case GS_Task_t.DISPLAY_DEV_PDF:
- case GS_Task_t.DISPLAY_DEV_THUMBS_NON_PDF:
- case GS_Task_t.DISPLAY_DEV_THUMBS_PDF:
+ case GS_Task_t.DISPLAY_DEV_THUMBS:
m_worker.DoWork += new DoWorkEventHandler(DisplayDeviceAsync);
break;
+ case GS_Task_t.DISPLAY_DEV_RUN_FILE:
+ m_worker.DoWork += new DoWorkEventHandler(DisplayDeviceRun);
+ break;
case GS_Task_t.SAVE_RESULT:
case GS_Task_t.CREATE_XPS:
default:
@@ -993,9 +1238,6 @@ public class gsEventArgs : EventArgs
gsparams.args.Add("gs");
gsparams.args.Add("-dNODISPLAY");
- gsparams.args.Add("-dNOPAUSE");
- gsparams.args.Add("-dBATCH");
- gsparams.args.Add("-I%rom%Resource/Init/");
//gsparams.args.Add("-q");
gsparams.args.Add("-sFile=\"" + fileName + "\"");
gsparams.args.Add("--permit-file-read=\"" + fileName + "\"");
@@ -1012,7 +1254,6 @@ public class gsEventArgs : EventArgs
return -1;
}
-#if WPF
/* Launch a thread to create XPS document for windows printing */
public gsStatus CreateXPS(String fileName, int resolution, int num_pages,
Print printsettings, int firstpage, int lastpage)
@@ -1022,13 +1263,10 @@ public class gsEventArgs : EventArgs
gsparams.inputfile = fileName;
gsparams.args.Add("gs");
- gsparams.args.Add("-dNOPAUSE");
- gsparams.args.Add("-dBATCH");
- gsparams.args.Add("-I%rom%Resource/Init/");
- gsparams.args.Add("-dSAFER");
gsparams.args.Add("-r" + resolution.ToString());
- gsparams.args.Add("-dNOCACHE");
gsparams.args.Add("-sDEVICE=xpswrite");
+ gsparams.args.Add("-dNOPAUSE");
+ gsparams.args.Add("-dBATCH");
gsparams.args.Add("-dFirstPage=" + firstpage.ToString());
gsparams.args.Add("-dLastPage=" + lastpage.ToString());
@@ -1064,10 +1302,10 @@ public class gsEventArgs : EventArgs
gsparams.args.Add("-f");
gsparams.args.Add(fileName);
gsparams.task = GS_Task_t.CREATE_XPS;
+ gsparams.num_pages = num_pages;
return RunGhostscriptAsync(gsparams);
}
-#endif
/* Launch a thread rendering all the pages with the display device
* to distill an input PS file and save as a PDF. */
@@ -1078,10 +1316,6 @@ public class gsEventArgs : EventArgs
gsparams.inputfile = fileName;
gsparams.args.Add("gs");
- gsparams.args.Add("-dNOPAUSE");
- gsparams.args.Add("-dBATCH");
- gsparams.args.Add("-I%rom%Resource/Init/");
- gsparams.args.Add("-dSAFER");
gsparams.args.Add("-sDEVICE=pdfwrite");
gsparams.outputfile = Path.GetTempFileName();
gsparams.args.Add("-o" + gsparams.outputfile);
@@ -1090,9 +1324,30 @@ public class gsEventArgs : EventArgs
return RunGhostscriptAsync(gsparams);
}
+ /* Run a file with the display device
+ * public gsStatus gsDsiplayDeviceRunFile() */
+ public gsStatus gsDisplayDeviceRunFile(String fileName, double zoom, bool aa, int firstpage, int lastpage)
+ {
+ gsParamState_t gsparams = new gsParamState_t();
+
+ gsparams.inputfile = fileName;
+ gsparams.aa = aa;
+ gsparams.zoom = zoom;
+ gsparams.firstpage = firstpage;
+ gsparams.lastpage = lastpage;
+ if (firstpage > 0)
+ gsparams.currpage = firstpage - 1;
+ else
+ gsparams.currpage = 0;
+
+ gsparams.task = GS_Task_t.DISPLAY_DEV_RUN_FILE;
+
+ return RunGhostscriptAsync(gsparams);
+ }
+
/* Launch a thread rendering all the pages with the display device
- * to collect thumbnail images or full resolution. */
- public gsStatus gsDisplayDeviceRenderAll(String fileName, double zoom, bool aa, GS_Task_t task)
+ * to collect thumbnail images via init_with_args. */
+ public gsStatus gsDisplayDeviceRenderThumbs(String fileName, double zoom, bool aa, GS_Task_t task)
{
gsParamState_t gsparams = new gsParamState_t();
int format = (gsConstants.DISPLAY_COLORS_RGB |
@@ -1102,10 +1357,7 @@ public class gsEventArgs : EventArgs
gsparams.args = new List<string>();
gsparams.args.Add("gs");
- gsparams.args.Add("-dNOPAUSE");
- gsparams.args.Add("-dBATCH");
- gsparams.args.Add("-I%rom%Resource/Init/");
- gsparams.args.Add("-dSAFER");
+ gsparams.args.Add("-dFirstPage=1"); /* To ensure gdevflp is setup */
gsparams.args.Add("-r" + resolution);
if (aa)
{
@@ -1122,7 +1374,6 @@ public class gsEventArgs : EventArgs
return RunGhostscriptAsync(gsparams);
}
-
/* Launch a thread rendering a set of pages with the display device. For use with languages
that can be indexed via pages which include PDF and XPS */
public gsStatus gsDisplayDeviceRenderPages(String fileName, int first_page, int last_page, double zoom)
@@ -1135,10 +1386,6 @@ public class gsEventArgs : EventArgs
gsparams.args = new List<string>();
gsparams.args.Add("gs");
- gsparams.args.Add("-dNOPAUSE");
- gsparams.args.Add("-dBATCH");
- gsparams.args.Add("-I%rom%Resource/Init/");
- gsparams.args.Add("-dSAFER");
gsparams.args.Add("-r" + resolution);
gsparams.args.Add("-sDEVICE=display");
gsparams.args.Add("-dDisplayFormat=" + format);
@@ -1152,6 +1399,72 @@ public class gsEventArgs : EventArgs
return RunGhostscriptAsync(gsparams);
}
+ /* Set up the display device ahead of time */
+ public gsParamState_t DisplayDeviceOpen()
+ {
+ int code;
+ gsParamState_t gsparams = new gsParamState_t();
+ gsparams.result = GS_Result_t.gsOK;
+
+ if (dispInstance != IntPtr.Zero)
+ return gsparams;
+
+ try
+ {
+ code = ghostapi.gsapi_new_instance(out dispInstance, IntPtr.Zero);
+ if (code < 0)
+ {
+ throw new GhostscriptException("DisplayDeviceOpen: gsapi_new_instance error");
+ }
+
+ code = ghostapi.gsapi_set_stdio(dispInstance, raise_stdin, raise_stdout, raise_stderr);
+ if (code < 0)
+ {
+ throw new GhostscriptException("DisplayDeviceOpen: gsapi_set_stdio error");
+ }
+
+ code = ghostapi.gsapi_set_arg_encoding(dispInstance, (int)gsEncoding.GS_ARG_ENCODING_UTF8);
+ if (code < 0)
+ {
+ throw new GhostscriptException("DisplayDeviceOpen: gsapi_set_arg_encoding error");
+ }
+
+ code = ghostapi.gsapi_set_display_callback(dispInstance, ptr_display_struct);
+ if (code < 0)
+ {
+ throw new GhostscriptException("DisplayDeviceOpen: gsapi_set_display_callback error");
+ }
+ }
+
+ catch (DllNotFoundException except)
+ {
+ gsDLLProblemMain("Exception: " + except.Message);
+ gsparams.result = GS_Result_t.gsFAILED;
+ }
+ catch (BadImageFormatException except)
+ {
+ gsDLLProblemMain("Exception: " + except.Message);
+ gsparams.result = GS_Result_t.gsFAILED;
+ }
+ catch (GhostscriptException except)
+ {
+ gsDLLProblemMain("Exception: " + except.Message);
+ gsparams.result = GS_Result_t.gsFAILED;
+ if (dispInstance != IntPtr.Zero)
+ ghostapi.gsapi_delete_instance(dispInstance);
+ dispInstance = IntPtr.Zero;
+ }
+ catch (Exception except)
+ {
+ gsDLLProblemMain("Exception: " + except.Message);
+ gsparams.result = GS_Result_t.gsFAILED;
+ if (dispInstance != IntPtr.Zero)
+ ghostapi.gsapi_delete_instance(dispInstance);
+ dispInstance = IntPtr.Zero;
+ }
+ return gsparams;
+ }
+
/* Close the display device and delete the instance */
public gsParamState_t DisplayDeviceClose()
{
@@ -1162,12 +1475,14 @@ public class gsEventArgs : EventArgs
try
{
- int code1 = ghostapi.gsapi_exit(dispInstance);
- if ((code == 0) || (code == gsConstants.E_QUIT))
- code = code1;
+ code = ghostapi.gsapi_exit(dispInstance);
+ if (code < 0)
+ {
+ out_params.result = GS_Result_t.gsFAILED;
+ throw new GhostscriptException("DisplayDeviceClose: gsapi_exit error");
+ }
ghostapi.gsapi_delete_instance(dispInstance);
- dispInstance = IntPtr.Zero;
}
catch (Exception except)
@@ -1176,6 +1491,8 @@ public class gsEventArgs : EventArgs
out_params.result = GS_Result_t.gsFAILED;
}
+ dispInstance = IntPtr.Zero;
+ m_displaystate.is_valid = false;
return out_params;
}
diff --git a/demos/csharp/windows/ghostnet_wpf_example/DocPage.cs b/demos/csharp/windows/ghostnet_wpf_example/DocPage.cs
index c28bd62d..93316d9d 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/DocPage.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/DocPage.cs
@@ -10,6 +10,7 @@ namespace ghostnet_wpf_example
private int height;
private int width;
private double zoom;
+ private bool aa;
private BitmapSource bitmap;
private String pagename;
private int pagenum;
@@ -41,6 +42,12 @@ namespace ghostnet_wpf_example
set { zoom = value; }
}
+ public bool AA
+ {
+ get { return aa; }
+ set { aa = value; }
+ }
+
public BitmapSource BitMap
{
get { return bitmap; }
@@ -90,12 +97,13 @@ namespace ghostnet_wpf_example
this.pagename = "";
}
- public DocPage(int Height, int Width, double Zoom, BitmapSource BitMap, int PageNum)
+ public DocPage(int Height, int Width, double Zoom, BitmapSource BitMap, int PageNum, bool AA)
{
this.height = Height;
this.width = Width;
this.zoom = Zoom;
this.bitmap = BitMap;
+ this.aa = AA;
this.pagename = ("Page " + (pagenum + 1));
}
};
diff --git a/demos/csharp/windows/ghostnet_wpf_example/MainPrint.cs b/demos/csharp/windows/ghostnet_wpf_example/MainPrint.cs
index e1c7a1e3..40855ba0 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/MainPrint.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/MainPrint.cs
@@ -6,6 +6,8 @@ using System.Windows.Xps.Packaging;
using System.Printing;
using System.Windows.Input;
using System.IO;
+using System.Diagnostics;
+using System.ComponentModel;
using GhostNET;
namespace ghostnet_wpf_example
@@ -14,6 +16,7 @@ namespace ghostnet_wpf_example
{
Print m_printcontrol = null;
private xpsprint m_xpsprint = null;
+ PrintStatus m_printstatus = null;
public void PrintDiagPrint(object PrintDiag)
{
@@ -38,14 +41,22 @@ namespace ghostnet_wpf_example
case PrintPages_t.ALL:
print_all = true;
first_page = 1;
- last_page = m_numpages + 1;
+ last_page = m_numpages;
break;
}
+ /* Show the progress bar dialog */
+ m_printstatus = new PrintStatus();
+ m_printstatus.Activate();
+ m_printstatus.Show();
+ string extension = System.IO.Path.GetExtension(m_currfile);
+
/* If file is already xps then gs need not do this */
- if (!(m_document_type == doc_t.XPS))
+ /* We are doing this based on the extension but like should do
+ * it based upon the content */
+ if ( !(String.Equals(extension.ToUpper(),"XPS") || String.Equals(extension.ToUpper(), "OXPS")) )
{
- xaml_DistillProgress.Value = 0;
+ m_printstatus.xaml_PrintProgress.Value = 0;
if (m_ghostscript.CreateXPS(m_currfile, Constants.DEFAULT_GS_RES,
last_page - first_page + 1, m_printcontrol, first_page, last_page) == gsStatus.GS_BUSY)
@@ -53,30 +64,41 @@ namespace ghostnet_wpf_example
ShowMessage(NotifyType_t.MESS_STATUS, "GS currently busy");
return;
}
- else
- {
- xaml_CancelDistill.Visibility = System.Windows.Visibility.Collapsed;
- xaml_DistillName.Text = "Convert to XPS";
- xaml_DistillName.FontWeight = FontWeights.Bold;
- xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible;
- }
}
else
PrintXPS(m_currfile, print_all, first_page, last_page, false);
}
+ /* Printing is achieved using xpswrite device in ghostscript and
+ * pushing that file through the XPS print queue. Since we can
+ * only have one instance of gs, this occurs on a separate
+ * process compared to the viewer. */
private void PrintCommand(object sender, ExecutedRoutedEventArgs e)
{
- Print(sender, e);
+ if (m_viewer_state != ViewerState_t.DOC_OPEN)
+ return;
+
+ /* Launch new process */
+ string path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
+ try
+ {
+ string Arguments = m_currfile + " print " + m_currpage + " " + m_numpages;
+ Process.Start(path, Arguments);
+ }
+ catch (InvalidOperationException)
+ {
+ Console.WriteLine("InvalidOperationException");
+ }
+ catch (Win32Exception)
+ {
+ Console.WriteLine("Win32 Exception: There was an error in opening the associated file. ");
+ }
+ return;
}
- /* Printing is achieved using xpswrite device in ghostscript and
- * pushing that file through the XPS print queue */
- private void Print(object sender, ExecutedRoutedEventArgs e)
+ private void Print(string FileName)
{
- if (!m_file_open)
- return;
-
+ m_currfile = FileName;
if (m_printcontrol == null)
{
m_printcontrol = new Print(this, m_numpages);
@@ -110,8 +132,11 @@ namespace ghostnet_wpf_example
m_xpsprint.PrintUpdate += PrintProgress;
arguments.Add(m_xpsprint);
- xaml_PrintGrid.Visibility = System.Windows.Visibility.Visible;
- xaml_PrintProgress.Value = 0;
+ m_printstatus.xaml_PrintProgressText.Text = "Printing...";
+ m_printstatus.xaml_PrintProgressText.FontWeight = FontWeights.Bold;
+ m_printstatus.xaml_PrintProgressGrid.Visibility = System.Windows.Visibility.Visible;
+ m_printstatus.xaml_PrintProgress.Value = 0;
+ m_viewer_state = ViewerState_t.PRINTING;
PrintThread.Start(arguments);
}
@@ -151,33 +176,23 @@ namespace ghostnet_wpf_example
switch (Information.Status)
{
case PrintStatus_t.PRINT_ERROR:
- System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
- {
- ShowMessage(NotifyType_t.MESS_ERROR, "Printer Driver Error");
- xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
- }));
- break;
case PrintStatus_t.PRINT_CANCELLED:
case PrintStatus_t.PRINT_READY:
- System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
- {
- xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
- }));
- break;
case PrintStatus_t.PRINT_DONE:
System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
{
- xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
- DeleteTempFile(Information.FileName);
+ if (File.Exists(Information.FileName))
+ DeleteTempFile(Information.FileName);
+ System.Windows.Application.Current.Shutdown();
}));
break;
case PrintStatus_t.PRINT_BUSY:
System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
{
- xaml_PrintProgress.Value = 100.0 * (double)(Information.Page - Information.PageStart) / (double)Information.NumPages;
+ m_printstatus.xaml_PrintProgress.Value = 100.0 * (double)(Information.Page - Information.PageStart) / (double)Information.NumPages;
if (Information.Page == Information.NumPages)
{
- xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
+ m_printstatus.xaml_PrintProgress.Visibility = System.Windows.Visibility.Collapsed;
}
}));
break;
diff --git a/demos/csharp/windows/ghostnet_wpf_example/MainRender.cs b/demos/csharp/windows/ghostnet_wpf_example/MainRender.cs
index 016c86bb..98661f98 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/MainRender.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/MainRender.cs
@@ -1,37 +1,42 @@
using System;
using System.Windows.Media;
-using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;
+using System.Windows.Controls;
using GhostNET;
namespace ghostnet_wpf_example
{
public partial class MainWindow
{
- bool m_busy_rendering;
- int m_firstpage;
- int m_lastpage;
-
- /* For PDF optimization */
+ /* Filter so we get the first non-full res and the last
+ * full res */
private void PageRangeRender(int first_page, int last_page)
{
- bool render_pages = false;
+ if (m_viewer_state != ViewerState_t.DOC_OPEN)
+ return;
+
+ int real_first_page = -1;
+ int real_last_page = -1;
+
for (int k = first_page; k <= last_page; k++)
{
- if (m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION)
+ if (real_first_page == -1 && ((m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION) ||
+ (m_docPages[k].AA != m_aa)))
{
- render_pages = true;
- break;
+ real_first_page = k;
+ }
+ if (m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION || m_docPages[k].AA != m_aa)
+ {
+ real_last_page = k;
}
}
- if (!render_pages)
+
+ if (real_first_page == -1)
return;
- m_busy_rendering = true;
- m_firstpage = first_page;
- m_lastpage = last_page;
- //m_ghostscript.gsDisplayDeviceRender(m_currfile, first_page + 1, last_page + 1, 1.0);
+ m_viewer_state = ViewerState_t.BUSY_RENDER;
+ m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, real_first_page + 1, real_last_page + 1);
}
/* Callback from ghostscript with the rendered image. */
@@ -51,15 +56,6 @@ namespace ghostnet_wpf_example
image_data.zoom = zoom_in;
m_images_rendered.Add(image_data);
- /* Get the 1.0 page scalings */
- if (m_firstime)
- {
- pagesizes_t page_size = new pagesizes_t();
- page_size.size.X = width;
- page_size.size.Y = height;
- m_page_sizes.Add(page_size);
- }
-
/* Dispatch progress bar update on UI thread */
System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send, new Action(() =>
{
@@ -71,65 +67,127 @@ namespace ghostnet_wpf_example
/* Done rendering. Update the pages with the new raster information if needed */
private void RenderingDone()
{
- int page_index = m_firstpage - 1;
- m_toppage_pos = new List<int>(m_images_rendered.Count + 1);
- int offset = 0;
-
for (int k = 0; k < m_images_rendered.Count; k++)
{
- DocPage doc_page = m_docPages[page_index + k];
+ DocPage doc_page = m_docPages[m_images_rendered[k].page_num - 1];
if (doc_page.Content != Page_Content_t.FULL_RESOLUTION ||
- m_aa_change)
+ doc_page.AA != m_aa)
{
doc_page.Width = m_images_rendered[k].width;
doc_page.Height = m_images_rendered[k].height;
doc_page.Content = Page_Content_t.FULL_RESOLUTION;
doc_page.Zoom = m_doczoom;
+ doc_page.AA = m_aa;
doc_page.BitMap = BitmapSource.Create(doc_page.Width, doc_page.Height,
72, 72, PixelFormats.Bgr24, BitmapPalettes.Halftone256, m_images_rendered[k].bitmap, m_images_rendered[k].raster);
}
- m_toppage_pos.Add(offset + Constants.PAGE_VERT_MARGIN);
- offset += doc_page.Height + Constants.PAGE_VERT_MARGIN;
}
xaml_ProgressGrid.Visibility = System.Windows.Visibility.Collapsed;
xaml_RenderProgress.Value = 0;
- m_aa_change = false;
- m_firstime = false;
- m_toppage_pos.Add(offset);
- m_busy_rendering = false;
m_images_rendered.Clear();
- m_file_open = true;
- m_busy_render = false;
- m_ghostscript.gsPageRenderedMain -= new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
+ m_viewer_state = ViewerState_t.DOC_OPEN;
}
- /* Render all pages full resolution */
- private void RenderMainFirst()
+ private Tuple<int, int> GetVisiblePages()
+ {
+ /* First child of list view */
+ Decorator border = VisualTreeHelper.GetChild(xaml_PageList, 0) as Decorator;
+
+ // Get scrollviewer
+ ScrollViewer scrollViewer = border.Child as ScrollViewer;
+
+ double top_window = scrollViewer.VerticalOffset;
+ double bottom_window = top_window + scrollViewer.ViewportHeight;
+ int first_page = -1;
+ int last_page = -1;
+
+ if (top_window > m_toppage_pos[m_numpages - 1])
+ {
+ first_page = m_numpages - 1;
+ last_page = first_page;
+ }
+ else
+ {
+ for (int k = 0; k < (m_toppage_pos.Count - 1); k++)
+ {
+ if (top_window <= m_toppage_pos[k + 1] && bottom_window >= m_toppage_pos[k])
+ {
+ if (first_page == -1)
+ {
+ first_page = k;
+ last_page = k;
+ }
+ else
+ {
+ last_page = k;
+ break;
+ }
+ }
+ else
+ {
+ if (first_page != -1)
+ {
+ last_page = first_page;
+ break;
+ }
+ }
+ }
+ }
+
+
+ return new Tuple<int, int>(first_page, last_page);
+ }
+
+ /* Render only visible pages. Used for single page formats as well
+ * as PDF (and ideally XPS) where the interpreter can interpret only
+ * specified pages */
+ private void RenderMainRange()
+ {
+ if (m_viewer_state == ViewerState_t.OPENING)
+ {
+ m_doczoom = 1.0;
+ xaml_Zoomsize.Text = "100";
+ m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
+ }
+
+ m_viewer_state = ViewerState_t.BUSY_RENDER;
+ (int first_page, int last_page) = GetVisiblePages();
+ m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, first_page + 1, last_page + 1);
+ }
+
+ /* Render all pages full resolution. Used for single page files as
+ * well as documents like PostScript and PCL that are not page
+ * based indexed */
+ private void RenderMainAll()
{
- m_firstpage = 1;
- m_busy_render = true;
xaml_RenderProgress.Value = 0;
xaml_ProgressGrid.Visibility = System.Windows.Visibility.Visible;
m_page_progress_count = 0;
xaml_RenderProgressText.Text = "Rendering";
- if (m_firstime)
+ if (m_viewer_state == ViewerState_t.OPENING)
{
+ m_doczoom = 1.0;
xaml_Zoomsize.Text = "100";
+ m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
}
- m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
- m_ghostscript.gsDisplayDeviceRenderAll(m_currfile, m_doczoom, m_aa, GS_Task_t.DISPLAY_DEV_NON_PDF);
+ m_viewer_state = ViewerState_t.BUSY_RENDER;
+ m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, -1, -1);
}
- /* Render all, but only if not already busy, called via zoom or aa changes */
- private void RenderMainAll()
+ /* Called via zoom or aa changes */
+ private void RenderMain()
{
- if (m_busy_render || !m_init_done)
+ if (m_viewer_state != ViewerState_t.DOC_OPEN)
return;
- RenderMainFirst();
+
+ if (m_doc_type_has_page_access)
+ RenderMainRange();
+ else
+ RenderMainAll();
}
}
}
diff --git a/demos/csharp/windows/ghostnet_wpf_example/MainThumbRendering.cs b/demos/csharp/windows/ghostnet_wpf_example/MainThumbRendering.cs
index 5db50389..102bb764 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/MainThumbRendering.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/MainThumbRendering.cs
@@ -18,13 +18,24 @@ namespace ghostnet_wpf_example
DocPage doc_page = new DocPage();
doc_page.Content = Page_Content_t.THUMBNAIL;
doc_page.Zoom = zoom_in;
+ doc_page.AA = m_aa;
doc_page.BitMap = m_thumbnails[page_num - 1].BitMap;
doc_page.Width = (int)(width / (Constants.SCALE_THUMB));
doc_page.Height = (int)(height / (Constants.SCALE_THUMB));
doc_page.PageNum = page_num;
m_docPages.Add(doc_page);
+
+ /* Set the page offsets. Used for determining which pages
+ * will be visible within viewport. */
m_toppage_pos.Add(offset + Constants.PAGE_VERT_MARGIN);
- offset += doc_page.Height + Constants.PAGE_VERT_MARGIN;
+ offset += doc_page.Height + 2 * Constants.PAGE_VERT_MARGIN;
+
+ /* Set page sizes for 1.0 scaling. This is used to quick
+ * rescale of pages prior to rendering at new zoom. */
+ pagesizes_t page_size = new pagesizes_t();
+ page_size.size.X = doc_page.Width;
+ page_size.size.Y = doc_page.Height;
+ m_page_sizes.Add(page_size);
}
/* Rendered all the thumbnail pages. Stick them in the appropriate lists */
@@ -58,7 +69,6 @@ namespace ghostnet_wpf_example
m_ghostscript.gsPageRenderedMain -= new ghostsharp.gsCallBackPageRenderedMain(gsThumbRendered);
-
m_numpages = m_list_thumb.Count;
if (m_numpages < 1)
{
@@ -67,13 +77,14 @@ namespace ghostnet_wpf_example
}
else
{
- m_init_done = true;
xaml_TotalPages.Text = "/" + m_numpages;
xaml_currPage.Text = m_currpage.ToString();
m_list_thumb.Clear();
- /* If non-pdf, kick off full page rendering */
- RenderMainFirst();
+ if (m_doc_type_has_page_access)
+ RenderMainRange();
+ else
+ RenderMainAll();
}
}
@@ -110,7 +121,7 @@ namespace ghostnet_wpf_example
xaml_ProgressGrid.Visibility = System.Windows.Visibility.Visible;
m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsThumbRendered);
- m_ghostscript.gsDisplayDeviceRenderAll(m_currfile, Constants.SCALE_THUMB, false, GS_Task_t.DISPLAY_DEV_THUMBS_NON_PDF);
+ m_ghostscript.gsDisplayDeviceRenderThumbs(m_currfile, Constants.SCALE_THUMB, false, GS_Task_t.DISPLAY_DEV_THUMBS);
}
}
}
diff --git a/demos/csharp/windows/ghostnet_wpf_example/MainWindow.xaml.cs b/demos/csharp/windows/ghostnet_wpf_example/MainWindow.xaml.cs
index 7ac077c2..f4b103b8 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/MainWindow.xaml.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/MainWindow.xaml.cs
@@ -9,6 +9,7 @@ using System.Diagnostics;
using Microsoft.Win32;
using GhostNET;
using System.IO;
+using System.Windows.Media;
static class Constants
{
@@ -51,6 +52,7 @@ namespace ghostnet_wpf_example
NOTSET,
BLANK
};
+
public enum zoom_t
{
NO_ZOOM,
@@ -64,9 +66,24 @@ namespace ghostnet_wpf_example
PDF,
PS,
PCL,
+ PNG,
+ EPS,
+ JPG,
+ TIF,
XPS
}
+ public enum ViewerState_t
+ {
+ NO_FILE,
+ OPENING,
+ BUSY_RENDER,
+ DOC_OPEN,
+ DISTILLING,
+ PRINTING,
+ RESIZING
+ }
+
public struct idata_t
{
public int page_num;
@@ -85,10 +102,9 @@ namespace ghostnet_wpf_example
public partial class MainWindow : Window
{
-
ghostsharp m_ghostscript;
- bool m_file_open;
doc_t m_document_type;
+ bool m_doc_type_has_page_access;
String m_currfile;
List<TempFile> m_tempfiles;
String m_origfile;
@@ -100,14 +116,11 @@ namespace ghostnet_wpf_example
public List<pagesizes_t> m_page_sizes;
List<idata_t> m_list_thumb;
List<idata_t> m_images_rendered;
- bool m_init_done;
- bool m_busy_render;
- bool m_firstime;
bool m_validZoom;
bool m_aa;
- bool m_aa_change;
List<int> m_toppage_pos;
int m_page_progress_count;
+ ViewerState_t m_viewer_state;
private static List<Page_Content_t> m_pageType;
@@ -132,6 +145,7 @@ namespace ghostnet_wpf_example
m_ghostscript.gsUpdateMain += new ghostsharp.gsCallBackMain(gsProgress);
m_ghostscript.gsIOUpdateMain += new ghostsharp.gsIOCallBackMain(gsIO);
m_ghostscript.gsDLLProblemMain += new ghostsharp.gsDLLProblem(gsDLL);
+ m_ghostscript.DisplayDeviceOpen();
m_currpage = 0;
m_gsoutput = new gsOutput();
@@ -141,30 +155,53 @@ namespace ghostnet_wpf_example
m_docPages = new Pages();
m_pageType = new List<Page_Content_t>();
m_page_sizes = new List<pagesizes_t>();
- m_file_open = false;
m_document_type = doc_t.UNKNOWN;
m_doczoom = 1.0;
- m_init_done = false;
- m_busy_render = true;
+ m_viewer_state = ViewerState_t.NO_FILE;
m_validZoom = true;
- m_firstime = true;
+ m_doc_type_has_page_access = true;
m_list_thumb = new List<idata_t>();
m_images_rendered = new List<idata_t>();
- m_busy_rendering = false;
m_aa = true;
- m_aa_change = false;
xaml_PageList.AddHandler(Grid.DragOverEvent, new System.Windows.DragEventHandler(Grid_DragOver), true);
xaml_PageList.AddHandler(Grid.DropEvent, new System.Windows.DragEventHandler(Grid_Drop), true);
- /* For case of opening another file */
+
+ /* For case of opening another file, or launching a print process */
string[] arguments = Environment.GetCommandLineArgs();
- if (arguments.Length > 1)
+ if (arguments.Length == 3)
{
string filePath = arguments[1];
- ProcessFile(filePath);
+ string job = arguments[2];
+
+ if (String.Equals(job, "open"))
+ ProcessFile(filePath);
+ }
+ else if (arguments.Length == 5)
+ {
+ string filePath = arguments[1];
+ string job = arguments[2];
+
+ try
+ {
+ m_currpage = Int32.Parse(arguments[3]);
+ m_numpages = Int32.Parse(arguments[4]);
+ }
+ catch (FormatException)
+ {
+ Console.WriteLine("Failure to parse print page info");
+ Close();
+ }
+
+ /* Keep main window hidden if we are doing a print process */
+ this.IsVisibleChanged += new System.Windows.DependencyPropertyChangedEventHandler(WindowVisible);
+ m_viewer_state = ViewerState_t.PRINTING;
+ Print(filePath);
}
+
}
+
private void gsIO(String mess, int len)
{
m_gsoutput.Update(mess, len);
@@ -198,8 +235,8 @@ namespace ghostnet_wpf_example
{
case GS_Task_t.CREATE_XPS:
- xaml_DistillProgress.Value = 100;
- xaml_DistillGrid.Visibility = System.Windows.Visibility.Collapsed;
+ m_printstatus.xaml_PrintProgress.Value = 100;
+ m_printstatus.xaml_PrintProgressGrid.Visibility = System.Windows.Visibility.Collapsed;
break;
case GS_Task_t.PS_DISTILL:
@@ -210,11 +247,11 @@ namespace ghostnet_wpf_example
case GS_Task_t.SAVE_RESULT:
break;
- case GS_Task_t.DISPLAY_DEV_THUMBS_NON_PDF:
- case GS_Task_t.DISPLAY_DEV_THUMBS_PDF:
+ case GS_Task_t.DISPLAY_DEV_THUMBS:
ThumbsDone();
break;
+ case GS_Task_t.DISPLAY_DEV_RUN_FILE:
case GS_Task_t.DISPLAY_DEV_PDF:
case GS_Task_t.DISPLAY_DEV_NON_PDF:
RenderingDone();
@@ -251,7 +288,7 @@ namespace ghostnet_wpf_example
switch (asyncInformation.Params.task)
{
case GS_Task_t.CREATE_XPS:
- this.xaml_DistillProgress.Value = asyncInformation.Progress;
+ m_printstatus.xaml_PrintProgress.Value = asyncInformation.Progress;
break;
case GS_Task_t.PS_DISTILL:
@@ -308,7 +345,6 @@ namespace ghostnet_wpf_example
switch (gs_result.task)
{
case GS_Task_t.CREATE_XPS:
- xaml_DistillGrid.Visibility = System.Windows.Visibility.Collapsed;
/* Always do print all from xps conversion as it will do
* the page range handling for us */
/* Add file to temp file list */
@@ -341,6 +377,7 @@ namespace ghostnet_wpf_example
}
tempfile.DeleteFile();
+ m_viewer_state = ViewerState_t.NO_FILE;
break;
case GS_Task_t.SAVE_RESULT:
@@ -357,8 +394,6 @@ namespace ghostnet_wpf_example
private void CleanUp()
{
- m_init_done = false;
-
/* Collapse this stuff since it is going to be released */
xaml_ThumbGrid.Visibility = System.Windows.Visibility.Collapsed;
@@ -381,23 +416,29 @@ namespace ghostnet_wpf_example
m_currfile = null;
m_origfile = null;
m_numpages = -1;
- m_file_open = false;
- m_firstime = true;
+ m_doc_type_has_page_access = true;
m_document_type = doc_t.UNKNOWN;
m_origfile = null;
CleanUpTempFiles();
- m_file_open = false;
- m_busy_render = true;
xaml_TotalPages.Text = "/ 0";
xaml_currPage.Text = "0";
CloseExtraWindows(false);
+ m_ghostscript.gsPageRenderedMain -= new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
+ m_ghostscript.DisplayDeviceClose();
+ m_ghostscript.DisplayDeviceOpen();
+ m_viewer_state = ViewerState_t.NO_FILE;
+
+ /* Set vertical scroll to top position */
+ Decorator border = VisualTreeHelper.GetChild(xaml_PageList, 0) as Decorator;
+ ScrollViewer scrollViewer = border.Child as ScrollViewer;
+ scrollViewer.ScrollToVerticalOffset(0);
return;
}
private void CloseCommand(object sender, ExecutedRoutedEventArgs e)
{
- if (m_init_done)
+ if (m_viewer_state == ViewerState_t.DOC_OPEN)
CleanUp();
}
@@ -420,7 +461,7 @@ namespace ghostnet_wpf_example
return;
OpenFileDialog dlg = new OpenFileDialog();
- dlg.Filter = "Document Files(*.ps;*.eps;*.pdf)|*.ps;*.eps;*.pdf;|All files (*.*)|*.*";
+ dlg.Filter = "Document Files(*.ps;*.eps;*.pdf;*.bin;*.xps;*.oxps;*.jpg;*.png;*.tif|*.ps;*.eps;*.pdf;*.bin;*.xps;*.oxps;*.jpg;*.png;*.tif|All files (*.*)|*.*";
dlg.FilterIndex = 1;
if (dlg.ShowDialog() == true)
ProcessFile(dlg.FileName);
@@ -435,7 +476,7 @@ namespace ghostnet_wpf_example
ShowMessage(NotifyType_t.MESS_STATUS, "File not found!");
return;
}
- if (m_file_open)
+ if (m_viewer_state == ViewerState_t.DOC_OPEN)
{
/* In this case, we want to go ahead and launch a new process
* handing it the filename */
@@ -443,7 +484,8 @@ namespace ghostnet_wpf_example
string path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
try
{
- Process.Start(path, FileName);
+ string Arguments = FileName + " open";
+ Process.Start(path, Arguments);
}
catch (InvalidOperationException)
{
@@ -455,6 +497,10 @@ namespace ghostnet_wpf_example
}
return;
}
+ else if (m_viewer_state != ViewerState_t.NO_FILE)
+ return;
+
+ m_viewer_state = ViewerState_t.OPENING;
/* If we have a ps or eps file then launch the distiller first
* and then we will get a temp pdf file which we will open. This is done
@@ -470,7 +516,7 @@ namespace ghostnet_wpf_example
m_document_type = doc_t.PS;
break;
case ".EPS":
- m_document_type = doc_t.PS;
+ m_document_type = doc_t.EPS;
break;
case ".PDF":
m_document_type = doc_t.PDF;
@@ -478,24 +524,40 @@ namespace ghostnet_wpf_example
case ".XPS":
m_document_type = doc_t.XPS;
break;
+ case ".OXPS":
+ m_document_type = doc_t.XPS;
+ break;
case ".BIN":
m_document_type = doc_t.PCL;
break;
+ case ".PNG":
+ m_document_type = doc_t.PNG;
+ break;
+ case ".JPG":
+ m_document_type = doc_t.JPG;
+ break;
+ case ".TIF":
+ m_document_type = doc_t.TIF;
+ break;
default:
{
m_document_type = doc_t.UNKNOWN;
ShowMessage(NotifyType_t.MESS_STATUS, "Unknown File Type");
+ m_viewer_state = ViewerState_t.NO_FILE;
return;
}
}
- if (extension.ToUpper() != ".PDF")
+ if (m_document_type == doc_t.PCL ||
+ m_document_type == doc_t.XPS ||
+ m_document_type == doc_t.PS)
{
- MessageBoxResult result = MessageBox.Show("Would you like to Distill this file?", "ghostnet", MessageBoxButton.YesNoCancel);
+ MessageBoxResult result = MessageBox.Show("Would you like to distill this file?", "ghostnet", MessageBoxButton.YesNoCancel);
switch (result)
{
case MessageBoxResult.Yes:
xaml_DistillProgress.Value = 0;
+ m_viewer_state = ViewerState_t.DISTILLING;
if (m_ghostscript.DistillPS(FileName, Constants.DEFAULT_GS_RES) == gsStatus.GS_BUSY)
{
ShowMessage(NotifyType_t.MESS_STATUS, "GS currently busy");
@@ -507,21 +569,23 @@ namespace ghostnet_wpf_example
xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible;
return;
case MessageBoxResult.No:
+ //m_doc_type_has_page_access = false;
break;
case MessageBoxResult.Cancel:
+ m_viewer_state = ViewerState_t.NO_FILE;
return;
}
}
m_currfile = FileName;
- //m_numpages = m_ghostscript.GetPageCount(m_currfile);
RenderThumbs();
return;
-
}
+
private void CancelDistillClick(object sender, RoutedEventArgs e)
{
}
+
private void DeleteTempFile(String file)
{
for (int k = 0; k < m_tempfiles.Count; k++)
@@ -557,6 +621,7 @@ namespace ghostnet_wpf_example
}
m_tempfiles.Clear();
}
+
private void OnAboutClick(object sender, RoutedEventArgs e)
{
About about = new About(this);
@@ -624,7 +689,7 @@ namespace ghostnet_wpf_example
{
e.Handled = true;
- if (!m_init_done || m_busy_rendering || m_toppage_pos == null)
+ if (m_viewer_state != ViewerState_t.DOC_OPEN)
return;
/* Find the pages that are visible. */
@@ -640,7 +705,7 @@ namespace ghostnet_wpf_example
}
else
{
- for (int k = 0; k < (m_toppage_pos.Count() - 1); k++)
+ for (int k = 0; k < (m_toppage_pos.Count - 1); k++)
{
if (top_window <= m_toppage_pos[k + 1] && bottom_window >= m_toppage_pos[k])
{
@@ -666,13 +731,9 @@ namespace ghostnet_wpf_example
m_currpage = first_page;
xaml_currPage.Text = (m_currpage + 1).ToString();
- /* Only PDF does this page sensitive approach */
- if (m_document_type != doc_t.PDF)
- return;
+ if (m_doc_type_has_page_access)
+ PageRangeRender(first_page, last_page);
- /* Disable for now. All do full doc rendering. NB implement
- * for XPS and PDF which allow direct page access */
- //PageRangeRender(first_page, last_page);
return;
}
private void Grid_DragOver(object sender, System.Windows.DragEventArgs e)
@@ -687,6 +748,15 @@ namespace ghostnet_wpf_example
}
e.Handled = false;
}
+
+ /* Keep main window hidden if we are doing a print process */
+ public void WindowVisible(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (m_viewer_state == ViewerState_t.PRINTING)
+ {
+ this.Visibility = Visibility.Hidden;
+ }
+ }
private void Grid_Drop(object sender, System.Windows.DragEventArgs e)
{
@@ -725,15 +795,13 @@ namespace ghostnet_wpf_example
private void AA_uncheck(object sender, RoutedEventArgs e)
{
m_aa = false;
- m_aa_change = true;
- RenderMainAll();
+ RenderMain();
}
private void AA_check(object sender, RoutedEventArgs e)
{
m_aa = true;
- m_aa_change = true;
- RenderMainAll();
+ RenderMain();
}
}
}
diff --git a/demos/csharp/windows/ghostnet_wpf_example/MainZoom.cs b/demos/csharp/windows/ghostnet_wpf_example/MainZoom.cs
index 0502e6c7..08e270e2 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/MainZoom.cs
+++ b/demos/csharp/windows/ghostnet_wpf_example/MainZoom.cs
@@ -3,6 +3,7 @@ using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;
using System.Windows.Input;
+using System.Windows.Media;
namespace ghostnet_wpf_example
{
@@ -51,7 +52,7 @@ namespace ghostnet_wpf_example
private bool ZoomDisabled()
{
- if (!m_init_done || m_busy_render)
+ if (m_viewer_state != ViewerState_t.DOC_OPEN)
return true;
else
return false;
@@ -61,26 +62,28 @@ namespace ghostnet_wpf_example
{
if (ZoomDisabled())
return;
- if (!m_init_done || m_doczoom <= Constants.ZOOM_MIN)
+
+ if (m_doczoom <= Constants.ZOOM_MIN)
return;
m_doczoom = GetNextZoom(m_doczoom, -1);
xaml_Zoomsize.Text = Math.Round(m_doczoom * 100.0).ToString();
ResizePages();
- RenderMainAll();
+ RenderMain();
}
private void ZoomIn(object sender, RoutedEventArgs e)
{
if (ZoomDisabled())
return;
- if (!m_init_done || m_doczoom >= Constants.ZOOM_MAX)
+
+ if (m_doczoom >= Constants.ZOOM_MAX)
return;
m_doczoom = GetNextZoom(m_doczoom, 1);
xaml_Zoomsize.Text = Math.Round(m_doczoom * 100.0).ToString();
ResizePages();
- RenderMainAll();
+ RenderMain();
}
private void ZoomTextChanged(object sender, TextChangedEventArgs e)
@@ -114,6 +117,9 @@ namespace ghostnet_wpf_example
if (e.Key == Key.Return)
{
+ if (ZoomDisabled())
+ return;
+
e.Handled = true;
var desired_zoom = xaml_Zoomsize.Text;
try
@@ -126,7 +132,7 @@ namespace ghostnet_wpf_example
m_doczoom = zoom;
ResizePages();
- RenderMainAll();
+ RenderMain();
xaml_Zoomsize.Text = Math.Round(zoom * 100.0).ToString();
}
catch (FormatException)
@@ -147,14 +153,22 @@ namespace ghostnet_wpf_example
if (m_page_sizes.Count == 0)
return;
+ int offset = 0;
+
+ /* Get scroll relative location */
+ Decorator border = VisualTreeHelper.GetChild(xaml_PageList, 0) as Decorator;
+ ScrollViewer scrollViewer = border.Child as ScrollViewer;
+ double top_window = scrollViewer.VerticalOffset;
+ double x_size = scrollViewer.ExtentHeight;
+
+ m_viewer_state = ViewerState_t.RESIZING;
for (int k = 0; k < m_numpages; k++)
{
var doc_page = m_docPages[k];
- if (doc_page.Zoom == m_doczoom &&
- doc_page.Width == (int)(m_doczoom * m_page_sizes[k].size.X) &&
- doc_page.Height == (int)(m_doczoom * m_page_sizes[k].size.Y))
- continue;
- else
+
+ if (doc_page.Zoom != m_doczoom ||
+ doc_page.Width != (int)(m_doczoom * m_page_sizes[k].size.X) ||
+ doc_page.Height != (int)(m_doczoom * m_page_sizes[k].size.Y))
{
/* Resize it now */
doc_page.Width = (int)(m_doczoom * m_page_sizes[k].size.X);
@@ -162,7 +176,18 @@ namespace ghostnet_wpf_example
doc_page.Zoom = m_doczoom;
doc_page.Content= Page_Content_t.OLD_RESOLUTION;
}
+
+ /* Adjust page top locations */
+ m_toppage_pos[k] = offset + Constants.PAGE_VERT_MARGIN;
+ offset += doc_page.Height + 2 * Constants.PAGE_VERT_MARGIN;
}
+
+ m_toppage_pos[m_numpages] = offset;
+ m_viewer_state = ViewerState_t.DOC_OPEN;
+
+ /* Reset scroll location */
+ /* This could probably be improved a bit. We should also do horizontal position */
+ scrollViewer.ScrollToVerticalOffset((top_window / x_size) * (double)offset);
}
}
} \ No newline at end of file
diff --git a/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml b/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml
new file mode 100644
index 00000000..7a40d169
--- /dev/null
+++ b/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml
@@ -0,0 +1,21 @@
+<Window x:Class="ghostnet_wpf_example.PrintStatus"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:local="clr-namespace:ghostnet_wpf_example"
+ mc:Ignorable="d"
+ Title="GhostNet Print Status" Height="116.25" Width="600">
+
+ <!-- The progress bar that runs while the pages are rendered -->
+ <Grid x:Name="xaml_PrintProgressGrid" DockPanel.Dock="Bottom" >
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <ProgressBar x:Name="xaml_PrintProgress" Grid.Row="0" Grid.Column="0" Margin="3" Minimum="0"
+ Maximum="100" Height="20" HorizontalAlignment="Stretch" />
+ <TextBlock x:Name="xaml_PrintProgressText" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="5, 0, 5, 0"><Bold>Creating XPS</Bold></TextBlock>
+ </Grid>
+</Window>
diff --git a/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml.cs b/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml.cs
new file mode 100644
index 00000000..41480471
--- /dev/null
+++ b/demos/csharp/windows/ghostnet_wpf_example/PrintStatus.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace ghostnet_wpf_example
+{
+ /// <summary>
+ /// Interaction logic for PrintStatus.xaml
+ /// </summary>
+ public partial class PrintStatus : Window
+ {
+ public PrintStatus()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/demos/csharp/windows/ghostnet_wpf_example/ghostnet_simple_viewer.csproj b/demos/csharp/windows/ghostnet_wpf_example/ghostnet_simple_viewer.csproj
index 895bff82..a7daf8f6 100644
--- a/demos/csharp/windows/ghostnet_wpf_example/ghostnet_simple_viewer.csproj
+++ b/demos/csharp/windows/ghostnet_wpf_example/ghostnet_simple_viewer.csproj
@@ -14,6 +14,21 @@
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -37,7 +52,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
- <DefineConstants>TRACE;DEBUG;WIN64;GHOSTPDL;WPF</DefineConstants>
+ <DefineConstants>TRACE;DEBUG;WIN64;GHOSTPDL</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
@@ -57,7 +72,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DefineConstants>TRACE;DEBUG;GHOSTPDL</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
@@ -74,6 +89,9 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
+ <PropertyGroup>
+ <RunPostBuildEvent>Always</RunPostBuildEvent>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="ReachFramework" />
<Reference Include="System" />
@@ -119,6 +137,9 @@
<Compile Include="PrintControl.xaml.cs">
<DependentUpon>PrintControl.xaml</DependentUpon>
</Compile>
+ <Compile Include="PrintStatus.xaml.cs">
+ <DependentUpon>PrintStatus.xaml</DependentUpon>
+ </Compile>
<Compile Include="TempFile.cs" />
<Compile Include="XPSprint.cs" />
<Page Include="About.xaml">
@@ -145,6 +166,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="PrintStatus.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
@@ -172,6 +197,18 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Debug (
diff --git a/demos/java/gsjava/.classpath b/demos/java/gsjava/.classpath
new file mode 100644
index 00000000..0cbf9cda
--- /dev/null
+++ b/demos/java/gsjava/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/java/gsjava/.project b/demos/java/gsjava/.project
new file mode 100644
index 00000000..45e10ae9
--- /dev/null
+++ b/demos/java/gsjava/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>gsjava</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/demos/java/gsjava/README.txt b/demos/java/gsjava/README.txt
new file mode 100644
index 00000000..07c55675
--- /dev/null
+++ b/demos/java/gsjava/README.txt
@@ -0,0 +1,149 @@
+Required libraries for this library:
+gpdldll64.dll
+gs_jni.dll
+
+Java Library:
+
+This library contains direct bindings to Ghostscript as
+well as several utility methods to make using the
+Ghostscript calls easier.
+
+The direct Ghostscript calls are found in
+com.artifex.gsjava.GSAPI and are named in the same way
+in which they are documented on https://www.ghostscript.com/doc/current/API.htm
+
+The com.artifex.gsjava.callbacks package contains
+interfaces which store interfaces and abstract classes
+used to implement Ghostscript callbacks in Java. These
+can be passed to Ghostscript through the GSAPI class.
+
+The com.artifex.gsjava.util package contains several
+classes to assist in passing parameters and handling
+native values. The Reference<T> and ByteArrayReference are
+the only classes which need to be used, however the others
+are avaliable if needed. The Reference class acts as
+a pointer parameter in a C function. An example use of this
+is in gsapi_new_instance which takes a Reference<Long> as
+a parameter. Calling the method would place the new
+Ghoscript instance in the Reference<Long>'s value field.
+
+The com.artifex.gsjava.GSInstance is a
+utility class. The GSInstance class stores an instance
+of Ghostscript and a client handle. The methods in this
+class are named the same in which they are documented without
+the need to pass the "instance" parameter through.
+
+The com.artifex.gsjava.devices package contains several
+classes representing Ghoscript devices. Using the classes
+in this package is the greatest amount of separation from
+using the raw Ghoscript calls and it requires no direct
+calls through the GSAPI class. All device classes in this
+package are extensions of Device which provides a way
+of setting up a Ghoscript device and setting parameters.
+Subclasses have utility methods to set individual parameters
+through method calls instead of using a String and parameter
+type to specify the parameter name and type, respectively.
+
+Example code segment to set up an instance of Ghoscript:
+
+import com.artifex.gsjava.*;
+import com.artifex.gsjava.util.*;
+
+public static void main(String[] args) {
+ // Stores a reference to the Ghoscript instance
+ Reference<Long> instanceReference = new Reference<>();
+
+ // Creates a new Ghoscript instance with a NULL caller handle,
+ // placing the instance into instanceReference
+ int code = GSAPI.gsapi_new_instance(instanceReference, GSAPI.GS_NULL);
+
+ if (code != GSAPI.GS_ERROR_OK) {
+ // An error has occured.
+ return;
+ }
+
+ // Returns the value the instanceReference references.
+ // This value is equivalent to a void * and has the same
+ // size in bytes.
+ long instance = instanceReference.getValue();
+
+ // Deletes the Ghoscript instance
+ GSAPI.gsapi_delete_instance(instance);
+}
+
+C++ Library:
+
+This library builds to gs_jni.dll and uses the
+Java Native Interface (JNI) to bind the functions in
+the GSAPI class to Ghoscript as well as handling callbacks,
+exceptions, and references.
+
+The bindings in GSAPI are in the header com_artifex_gsjava_GSJAVA.h
+and the implementations are in com_artifex_gsjava_GSJAVA.cpp.
+
+Utility methods for throwing exceptions, setting fields, calling
+Java methods, and using the Reference<T> class are declared
+in jni_util.h.
+
+Example method explaining the implementation for
+gsapi_run_string_begin:
+
+
+/* JNIEnv *env - Provided the JNI. Allows interfacing into calling Java methods,
+ * setting Java fields, etc. Different threads have different JNIEnv objects.
+ *
+ * jclass - Provided by the JNI. It represents the class calling this method.
+ *
+ * jlong instance - Instance to be passed to gsapi_run_string_begin
+ *
+ * jint userErrors - User errors to be passed to gsapi_run_string_begin
+ *
+ * jobject pExitCode - A Reference<Integer> object. This is always the case as the Java
+ * code will not allow anything else to be passed. The value which Ghostscript returns
+ * in the pExitCode parameter will be placed into here.
+ */
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin
+ (JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode)
+{
+ // Declares the exitCode parameter which will be passed as a pointer
+ // to gsapi_run_string_begin
+ int exitCode;
+
+ // Different threads have different JNIEnv objects, so each time a JNI method
+ // is called, this must be set so the Java callback methods can be called.
+ callbacks::setJNIEnv(env);
+
+ // Calls the Ghoscript call gsapi_run_string_begin
+ int code = gsapi_run_string_begin((void *)instance, userErrors, &exitCode);
+
+ // If the reference is not NULL, set the value of the reference to the exitCode returned
+ // from Ghoscript. It must be converted to the wrapper type java.lang.Integer as Java does not support
+ // primitive generic arguments (i.e. int, float, char, etc.)
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+
+ // Return the error code returned by Ghostscript
+ return code;
+}
+
+Viewer:
+
+There is an eclipse project containing a viewer using the
+Java Ghostscript bindings in gsjava. The eclipse project is
+set up such that the gsjava eclipse project must be built
+to a jar file and used in the gsviewer eclipse project.
+
+The viewer is designed to load PDF documents, but can also
+load other files like PostScript files and distill them into
+a PDF document to be opened.
+
+When the document is first loaded, every page is rendered at
+a low resolution. These will be displayed as thumbnails on the
+left side. All loadingg is done in the com.artifex.gsjava.Document
+class. As the user changes the position of the viewport, the
+viewer will dynamically load high resolution images based on
+what page the user is viewing. This is done in the
+com.artifex.gsviewer.ViewerController.SmartLoader class. This
+also handles rendering zoomed images if necessary. Only pages
+which need to be loaded at a high resolution are loaded, and
+zoomed pages are unloaded when no longer necessary to save memory. \ No newline at end of file
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/GSAPI.java b/demos/java/gsjava/src/com/artifex/gsjava/GSAPI.java
new file mode 100644
index 00000000..f275e417
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/GSAPI.java
@@ -0,0 +1,284 @@
+package com.artifex.gsjava;
+
+import java.util.List;
+
+import com.artifex.gsjava.callbacks.DisplayCallback;
+import com.artifex.gsjava.callbacks.ICalloutFunction;
+import com.artifex.gsjava.callbacks.IPollFunction;
+import com.artifex.gsjava.callbacks.IStdErrFunction;
+import com.artifex.gsjava.callbacks.IStdInFunction;
+import com.artifex.gsjava.callbacks.IStdOutFunction;
+import com.artifex.gsjava.util.Reference;
+import com.artifex.gsjava.util.StringUtil;
+
+/**
+ * Class which contains native bindings to Ghostscript via the JNI.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class GSAPI {
+
+ static {
+ registerLibraries();
+ }
+
+ /**
+ * Registers the needed native libraries.
+ */
+ private static void registerLibraries() {
+ System.loadLibrary("gs_jni");
+ }
+
+ /**
+ * NULL
+ */
+ public static final long GS_NULL = 0L;
+
+ /**
+ * Error codes
+ */
+ public static final int GS_ERROR_OK = 0,
+ GS_ERROR_UNKNOWNERROR = -1,
+ GS_ERROR_DICTFULL = -2,
+ GS_ERROR_DICTSTACKOVERFLOW = -3,
+ GS_ERROR_DICTSTACKUNDERFLOW = -4,
+ GS_ERROR_EXECSTACKOVERFLOW = -5,
+ GS_ERROR_INTERRUPT = -6,
+ GS_ERROR_INVALIDACCESS = -7,
+ GS_ERROR_INVALIDEXIT = -8,
+ GS_ERROR_INVALIDFILEACCESS = -9,
+ GS_ERROR_INVALIDFONT = -10,
+ GS_ERROR_INVALIDRESTORE = -11,
+ GS_ERROR_IOERROR = -12,
+ GS_ERROR_LIMITCHECK = -13,
+ GS_ERROR_NOCURRENTPOINT = -14,
+ GS_ERROR_RANGECHECK = -15,
+ GS_ERROR_STACKOVERFLOW = -16,
+ GS_ERROR_STACKUNDERFLOW = -17,
+ GS_ERROR_SYNTAXERROR = -18,
+ GS_ERROR_TIMEOUT = -19,
+ GS_ERROR_TYPECHECK = -20,
+ GS_ERROR_UNDEFINED = -21,
+ GS_ERROR_UNDEFINEDFILENAME = -22,
+ GS_ERROR_UNDEFINEDRESULT = -23,
+ GS_ERROR_UNMATCHEDMARK = -24,
+ GS_ERROR_VMERROR = -25;
+
+ /**
+ * Error codes
+ */
+ public static final int GS_ERROR_CONFIGURATION_ERROR = -26,
+ GS_ERROR_UNDEFINEDRESOURCE = -27,
+ GS_ERROR_UNREGISTERED = -28,
+ GS_ERROR_INVALIDCONTEXT = -29,
+ GS_ERROR_INVALID = -30;
+
+ public static final int GS_COLORS_NATIVE = (1 << 0),
+ GS_COLORS_GRAY = (1 << 1),
+ GS_COLORS_RGB = (1 << 2),
+ GS_COLORS_CMYK = (1 << 3),
+ GS_DISPLAY_COLORS_SEPARATION = (1 << 19);
+
+ public static final long GS_DISPLAY_COLORS_MASK = 0x8000fL;
+
+ public static final int GS_DISPLAY_ALPHA_NONE = (0 << 4),
+ GS_DISPLAY_ALPHA_FIRST = (1 << 4),
+ GS_DISPLAY_ALPHA_LAST = (1 << 5),
+ GS_DISPLAY_UNUSED_FIRST = (1 << 6),
+ GS_DISPLAY_UNUSED_LAST = (1 << 7);
+
+ public static final long GS_DISPLAY_ALPHA_MASK = 0x00f0L;
+
+ public static final int GS_DISPLAY_DEPTH_1 = (1 << 8),
+ GS_DISPLAY_DEPTH_2 = (1 << 9),
+ GS_DISPLAY_DEPTH_4 = (1 << 10),
+ GS_DISPLAY_DEPTH_8 = (1 << 11),
+ GS_DISPLAY_DEPTH_12 = (1 << 12),
+ GS_DISPLAY_DEPTH_16 = (1 << 3);
+
+ public static final long GS_DISPLAY_DEPTH_MASK = 0xff00L;
+
+ public static final int GS_DISPLAY_BIGENDIAN = (0 << 16),
+ GS_DISPLAY_LITTLEENDIAN = (1 << 16);
+
+ public static final long GS_DISPLAY_ENDIAN_MASK = 0x00010000L;
+
+ public static final int GS_DISPLAY_TOPFIRST = (0 << 17),
+ GS_DISPLAY_BOTTOMFIRST = (1 << 17);
+
+ public static final long GS_DISPLAY_FIRSTROW_MASK = 0x00020000L;
+
+ public static final int GS_SPT_INVALID = -1,
+ GS_SPT_NULL = 0,
+ GS_SPT_BOOL = 1,
+ GS_SPT_INT = 2,
+ GS_SPT_FLOAT = 3,
+ GS_SPT_NAME = 4,
+ GS_SPT_STRING = 5,
+ GS_SPT_LONG = 6,
+ GS_SPT_I64 = 7,
+ GS_SPT_SIZE_T = 8,
+ GS_SPT_PARSED = 9,
+ GS_SPT_MORE_TO_COME = 1 << 31;
+
+ /**
+ * Class used to store version information about Ghostscript.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+ public static class Revision {
+ public volatile byte[] product;
+ public volatile byte[] copyright;
+ public volatile long revision;
+ public volatile long revisionDate;
+
+ public Revision() {
+ this.product = null;
+ this.copyright = null;
+ this.revision = 0L;
+ this.revisionDate = 0L;
+ }
+
+ /**
+ * Returns the product information as a String.
+ *
+ * @return The product information.
+ */
+ public String getProduct() {
+ return new String(product);
+ }
+
+ /**
+ * Returns the copyright information as a String.
+ *
+ * @return The copyright information.
+ */
+ public String getCopyright() {
+ return new String(copyright);
+ }
+ }
+
+ // Don't let this class be instantiated
+ private GSAPI() { }
+
+ public static native int gsapi_revision(GSAPI.Revision revision, int len);
+
+ public static native int gsapi_new_instance(Reference<Long> instance, long callerHandle);
+
+ public static native void gsapi_delete_instance(long instance);
+
+ public static native int gsapi_set_stdio_with_handle(long instance, IStdInFunction stdin,
+ IStdOutFunction stdout, IStdErrFunction stderr, long callerHandle);
+
+ public static native int gsapi_set_stdio(long instance, IStdInFunction stdin, IStdOutFunction stdout,
+ IStdErrFunction stderr);
+
+ public static native int gsapi_set_poll_with_handle(long instance, IPollFunction pollfun, long callerHandle);
+
+ public static native int gsapi_set_poll(long instance, IPollFunction pollfun);
+
+ public static native int gsapi_set_display_callback(long instance, DisplayCallback displayCallback);
+
+ public static native int gsapi_register_callout(long instance, ICalloutFunction callout, long calloutHandle);
+
+ public static native void gsapi_deregister_callout(long instance, ICalloutFunction callout, long calloutHandle);
+
+ public static native int gsapi_set_arg_encoding(long instance, int encoding);
+
+ public static native int gsapi_set_default_device_list(long instance, byte[] list, int listlen);
+
+ public static native int gsapi_get_default_device_list(long instance, Reference<byte[]> list, Reference<Integer> listlen);
+
+ public static native int gsapi_init_with_args(long instance, int argc, byte[][] argv);
+
+ public static native int gsapi_run_string_begin(long instance, int userErrors, Reference<Integer> pExitCode);
+
+ public static native int gsapi_run_string_continue(long instance, byte[] str, int length, int userErrors,
+ Reference<Integer> pExitCode);
+
+ public static native int gsapi_run_string_end(long instance, int userErrors, Reference<Integer> pExitCode);
+
+ public static native int gsapi_run_string_with_length(long instance, byte[] str, int length, int userErrors,
+ Reference<Integer> pExitCode);
+
+ public static native int gsapi_run_string(long instance, byte[] str, int userErrors, Reference<Integer> pExitCode);
+
+ public static native int gsapi_run_file(long instance, byte[] fileName, int userErrors, Reference<Integer> pExitCode);
+
+ public static native int gsapi_exit(long instance);
+
+ public static native int gsapi_set_param(long instance, byte[] param, Object value, int paramType);
+
+ public static native int gsapi_get_param(long instance, byte[] param, long value, int paramType);
+
+ public static native int gsapi_get_param_once(long instance, byte[] param, Reference<?> value, int paramType);
+
+ public static native int gsapi_enumerate_params(long instance, Reference<Long> iter, Reference<byte[]> key, Reference<Integer> paramType);
+
+ public static native int gsapi_add_control_path(long instance, int type, byte[] path);
+
+ public static native int gsapi_remove_control_path(long instance, int type, byte[] path);
+
+ public static native void gsapi_purge_control_paths(long instance, int type);
+
+ public static native void gsapi_activate_path_control(long instance, boolean enable);
+
+ public static native boolean gsapi_is_path_control_active(long instance);
+
+ // Utility methods to make calling some native methods easier
+
+ public static int gsapi_init_with_args(long instance, String[] argv) {
+ return gsapi_init_with_args(instance, argv.length, StringUtil.to2DByteArray(argv));
+ }
+
+ public static int gsapi_init_with_args(long instance, List<String> argv) {
+ return gsapi_init_with_args(instance, argv.toArray(new String[argv.size()]));
+ }
+
+ public static int gsapi_run_string_continue(long instance, String str, int length, int userErrors,
+ Reference<Integer> pExitCode) {
+ return gsapi_run_string_continue(instance, StringUtil.toNullTerminatedByteArray(str.substring(0, length)),
+ length, userErrors, pExitCode);
+ }
+
+ public static int gsapi_run_string_with_length(long instance, String str, int length, int userErrors,
+ Reference<Integer> pExitCode) {
+ return gsapi_run_string_with_length(instance, StringUtil.toNullTerminatedByteArray(str.substring(0, length)),
+ length, userErrors, pExitCode);
+ }
+
+ public static int gsapi_run_string(long instance, String str, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string(instance, StringUtil.toNullTerminatedByteArray(str), userErrors, pExitCode);
+ }
+
+ public static int gsapi_run_file(long instance, String fileName, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_file(instance, StringUtil.toNullTerminatedByteArray(fileName), userErrors, pExitCode);
+ }
+
+ public static int gsapi_set_param(long instnace, String param, String value, int paramType) {
+ return gsapi_set_param(instnace, StringUtil.toNullTerminatedByteArray(param),
+ StringUtil.toNullTerminatedByteArray(value), paramType);
+ }
+
+ public static int gsapi_set_param(long instnace, String param, Object value, int paramType) {
+ return gsapi_set_param(instnace, StringUtil.toNullTerminatedByteArray(param), value, paramType);
+ }
+
+ public static int gsapi_get_param(long instance, String param, long value, int paramType) {
+ return gsapi_get_param(instance, StringUtil.toNullTerminatedByteArray(param), value, paramType);
+ }
+
+ public static int gsapi_get_param_once(long instance, String param, Reference<?> value, int paramType) {
+ return gsapi_get_param_once(instance, StringUtil.toNullTerminatedByteArray(param), value, paramType);
+ }
+
+ public static int gsapi_add_control_path(long instance, int type, String path) {
+ return gsapi_add_control_path(instance, type, StringUtil.toNullTerminatedByteArray(path));
+ }
+
+ public static int gsapi_remove_control_path(long instance, int type, String path) {
+ return gsapi_remove_control_path(instance, type, StringUtil.toNullTerminatedByteArray(path));
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java b/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java
new file mode 100644
index 00000000..e5e713c7
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java
@@ -0,0 +1,320 @@
+package com.artifex.gsjava;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.artifex.gsjava.callbacks.DisplayCallback;
+import com.artifex.gsjava.callbacks.ICalloutFunction;
+import com.artifex.gsjava.callbacks.IPollFunction;
+import com.artifex.gsjava.callbacks.IStdErrFunction;
+import com.artifex.gsjava.callbacks.IStdInFunction;
+import com.artifex.gsjava.callbacks.IStdOutFunction;
+import com.artifex.gsjava.util.ByteArrayReference;
+import com.artifex.gsjava.util.Reference;
+
+/**
+ * Utility class to make Ghostscript calls easier by storing a
+ * Ghostscript instance and, optionally, a caller handle.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class GSInstance implements Iterable<GSInstance.GSParam<?>> {
+
+ public static class GSParam<V> {
+
+ public final String key;
+ public final V value;
+
+ public GSParam(String key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public GSParam(V value) {
+ this(null, value);
+ }
+
+ public boolean canConvertToString() {
+ return value instanceof String || value instanceof byte[];
+ }
+
+ public String stringValue() {
+ if (value instanceof String)
+ return (String)value;
+ else if (value instanceof byte[])
+ return new String((byte[])value);
+ throw new IllegalStateException("Value cannot be converted to string");
+ }
+
+ @Override
+ public String toString() {
+ return key + " -> " + (canConvertToString() ? stringValue() : value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (o == this)
+ return true;
+ if (o instanceof GSParam) {
+ GSParam<?> other = (GSParam<?>)o;
+ return (key == null ? other.key == null : key.equals(other.key)) &&
+ (value == null ? other.value == null : value.equals(other.value));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode() + (value == null ? 0 : value.hashCode());
+ }
+ }
+
+ private static volatile boolean instanceExists = false;
+
+ private long instance;
+ private long callerHandle;
+
+ public GSInstance(long callerHandle) throws IllegalStateException {
+ if (instanceExists)
+ throw new IllegalStateException("An instance already exists");
+ Reference<Long> ref = new Reference<>();
+ int ret = gsapi_new_instance(ref, callerHandle);
+ if (ret != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to create new instance: " + ret);
+ this.instance = ref.getValue();
+ this.callerHandle = callerHandle;
+ instanceExists = true;
+ }
+
+ public GSInstance() throws IllegalStateException {
+ this(GS_NULL);
+ }
+
+ public void delete_instance() {
+ if (instance != GS_NULL)
+ gsapi_delete_instance(instance);
+ instance = GS_NULL;
+ instanceExists = false;
+ }
+
+ public int set_stdio(IStdInFunction stdin, IStdOutFunction stdout, IStdErrFunction stderr) {
+ return gsapi_set_stdio_with_handle(instance, stdin, stdout, stderr, callerHandle);
+ }
+
+ public int set_poll(IPollFunction pollfun) {
+ return gsapi_set_poll_with_handle(instance, pollfun, callerHandle);
+ }
+
+ public int set_display_callback(DisplayCallback displaycallback) {
+ return gsapi_set_display_callback(instance, displaycallback);
+ }
+
+ public int register_callout(ICalloutFunction callout) {
+ return gsapi_register_callout(instance, callout, callerHandle);
+ }
+
+ public void deregister_callout(ICalloutFunction callout) {
+ gsapi_deregister_callout(instance, callout, callerHandle);
+ }
+
+ public int set_arg_encoding(int encoding) {
+ return gsapi_set_arg_encoding(instance, encoding);
+ }
+
+ public int set_default_device_list(byte[] list, int listlen) {
+ return gsapi_set_default_device_list(instance, list, listlen);
+ }
+
+ public int get_default_device_list(Reference<byte[]> list, Reference<Integer> listlen) {
+ return gsapi_get_default_device_list(instance, list, listlen);
+ }
+
+ public int init_with_args(int argc, byte[][] argv) {
+ return gsapi_init_with_args(instance, argc, argv);
+ }
+
+ public int init_with_args(String[] argv) {
+ return gsapi_init_with_args(instance, argv);
+ }
+
+ public int init_with_args(List<String> argv) {
+ return gsapi_init_with_args(instance, argv);
+ }
+
+ public int run_string_begin(int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string_begin(instance, userErrors, pExitCode);
+ }
+
+ public int run_string_continue(byte[] str, int length, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string_continue(instance, str, length, userErrors, pExitCode);
+ }
+
+ public int run_string_continue(String str, int length, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string_continue(instance, str, length, userErrors, pExitCode);
+ }
+
+ public int run_string(byte[] str, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string(instance, str, userErrors, pExitCode);
+ }
+
+ public int run_string(String str, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_string(instance, str, userErrors, pExitCode);
+ }
+
+ public int run_file(byte[] fileName, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_file(instance, fileName, userErrors, pExitCode);
+ }
+
+ public int run_file(String filename, int userErrors, Reference<Integer> pExitCode) {
+ return gsapi_run_file(instance, filename, userErrors, pExitCode);
+ }
+
+ public int exit() {
+ return gsapi_exit(instance);
+ }
+
+ public int set_param(byte[] param, Object value, int paramType) {
+ return gsapi_set_param(instance, param, value, paramType);
+ }
+
+ public int set_param(String param, String value, int paramType) {
+ return gsapi_set_param(instance, param, value, paramType);
+ }
+
+ public int set_param(String param, Object value, int paramType) {
+ return gsapi_set_param(instance, param, value, paramType);
+ }
+
+ public int get_param(byte[] param, long value, int paramType) {
+ return gsapi_get_param(instance, param, value, paramType);
+ }
+
+ public int get_param(String param, long value, int paramType) {
+ return gsapi_get_param(instance, param, value, paramType);
+ }
+
+ public int get_param_once(byte[] param, Reference<?> value, int paramType) {
+ return gsapi_get_param_once(instance, param, value, paramType);
+ }
+
+ public int get_param_once(String param, Reference<?> value, int paramType) {
+ return gsapi_get_param_once(instance, param, value, paramType);
+ }
+
+ public int enumerate_params(Reference<Long> iter, Reference<byte[]> key, Reference<Integer> paramType) {
+ return gsapi_enumerate_params(instance, iter, key, paramType);
+ }
+
+ public int add_control_path(int type, byte[] path) {
+ return gsapi_add_control_path(instance, type, path);
+ }
+
+ public int add_control_path(int type, String path) {
+ return gsapi_add_control_path(instance, type, path);
+ }
+
+ public int remove_control_path(int type, byte[] path) {
+ return gsapi_remove_control_path(instance, type, path);
+ }
+
+ public int remove_control_path(int type, String path) {
+ return gsapi_remove_control_path(instance, type, path);
+ }
+
+ public void purge_control_paths(int type) {
+ gsapi_purge_control_paths(instance, type);
+ }
+
+ public void activate_path_control(boolean enable) {
+ gsapi_activate_path_control(instance, enable);
+ }
+
+ public boolean is_path_control_active() {
+ return gsapi_is_path_control_active(instance);
+ }
+
+ public GSParam<?>[] getParamArray() {
+ List<GSParam<?>> params = new LinkedList<>();
+ for (GSParam<?> param : this) {
+ params.add(param);
+ }
+ return params.toArray(new GSParam<?>[params.size()]);
+ }
+
+ @Override
+ public void finalize() {
+ if (instance != GS_NULL) {
+ exit();
+ delete_instance();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (o == this)
+ return true;
+ if (o instanceof GSInstance) {
+ GSInstance g = (GSInstance)o;
+ return g.instance == instance && g.callerHandle == callerHandle;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "GSInstance[instance=0x" + Long.toHexString(instance) + "]";
+ }
+
+ @Override
+ public Iterator<GSParam<?>> iterator() {
+ return new ParamIterator();
+ }
+
+ private class ParamIterator implements Iterator<GSParam<?>> {
+
+ private Reference<Long> iterator;
+ private ByteArrayReference key;
+ private Reference<Integer> valueType;
+ private Reference<?> value;
+
+ private int returnCode;
+
+ private ParamIterator() {
+ iterator = new Reference<>(0L);
+ key = new ByteArrayReference();
+ valueType = new Reference<>();
+ value = new Reference<>();
+ }
+
+ @Override
+ public boolean hasNext() {
+ long lastValue = iterator.getValue();
+ returnCode = enumerate_params(iterator, null, null);
+ iterator.setValue(lastValue);
+ return returnCode != 1;
+ }
+
+ @Override
+ public GSParam<?> next() {
+ if (returnCode != 0)
+ throw new IllegalStateException("Reached end of iterator");
+ returnCode = enumerate_params(iterator, key, valueType);
+ if (returnCode < 0)
+ throw new IllegalStateException("Failed to enumerate params");
+
+ int code = get_param_once(key.getValue(), value, valueType.getValue());
+ if (code != 0)
+ throw new IllegalStateException("Failed to get param");
+ return new GSParam<>(key.asString(), value.getValue());
+ }
+
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/DisplayCallback.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/DisplayCallback.java
new file mode 100644
index 00000000..f2f7e712
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/DisplayCallback.java
@@ -0,0 +1,75 @@
+package com.artifex.gsjava.callbacks;
+
+import com.artifex.gsjava.util.BytePointer;
+import com.artifex.gsjava.util.Reference;
+
+/**
+ * Class wrapping a display_callback structure.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public abstract class DisplayCallback {
+
+ public volatile int size;
+ public volatile int versionMajor;
+ public volatile int versionMinor;
+
+ public int onDisplayOpen(long handle, long device) {
+ return 0;
+ }
+
+ public int onDisplayPreclose(long handle, long device) {
+ return 0;
+ }
+
+ public int onDisplayClose(long handle, long device) {
+ return 0;
+ }
+
+ public int onDisplayPresize(long handle, long device, int width,
+ int height, int raster, int format) {
+ return 0;
+ }
+
+ public int onDisplaySize(long handle, long device, int width,
+ int height,int raster, int format, BytePointer pimage) {
+ return 0;
+ }
+
+ public int onDisplaySync(long handle, long device) {
+ return 0;
+ }
+
+ public int onDisplayPage(long handle, long device, int copies, boolean flush) {
+ return 0;
+ }
+
+ public int onDisplayUpdate(long handle, long device, int x, int y, int w, int h) {
+ return 0;
+ }
+
+ /*
+ public long onDisplayMemalloc(long handle, long device, long size) {
+ return GS_NULL;
+ }
+
+ public int onDisplayMemfree(long handle, long device, long mem) {
+ return 0;
+ }*/
+
+ public int onDisplaySeparation(long handle, long device, int component, byte[] componentName,
+ short c, short m, short y, short k) {
+ return 0;
+ }
+
+ public int onDisplayAdjustBandHeight(long handle, long device, int bandHeight) {
+ return 0;
+ }
+
+ public int onDisplayRectangleRequest(long handle, long device, Reference<Long> memory, Reference<Integer> ox,
+ Reference<Integer> oy, Reference<Integer> raster, Reference<Integer> planeRaster, Reference<Integer> x,
+ Reference<Integer> y, Reference<Integer> w, Reference<Integer> h) {
+ return 0;
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/ICalloutFunction.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/ICalloutFunction.java
new file mode 100644
index 00000000..9b163717
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/ICalloutFunction.java
@@ -0,0 +1,7 @@
+package com.artifex.gsjava.callbacks;
+
+@FunctionalInterface
+public interface ICalloutFunction {
+
+ public int onCallout(long instance, long calloutHandle, byte[] deviceName, int id, int size, long data);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IPollFunction.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IPollFunction.java
new file mode 100644
index 00000000..ae0f3b50
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IPollFunction.java
@@ -0,0 +1,7 @@
+package com.artifex.gsjava.callbacks;
+
+@FunctionalInterface
+public interface IPollFunction {
+
+ public int onPoll(long callerHandle);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdErrFunction.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdErrFunction.java
new file mode 100644
index 00000000..5001b9c5
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdErrFunction.java
@@ -0,0 +1,15 @@
+package com.artifex.gsjava.callbacks;
+
+@FunctionalInterface
+public interface IStdErrFunction {
+
+ /**
+ * Called when something should be written to the standard error stream.
+ *
+ * @param callerHandle The caller handle.
+ * @param str The string to write.
+ * @param len The length of bytes to be written.
+ * @return The amount of bytes written, must be <code>len</code>.
+ */
+ public int onStdErr(long callerHandle, byte[] str, int len);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdInFunction.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdInFunction.java
new file mode 100644
index 00000000..c6d97e94
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdInFunction.java
@@ -0,0 +1,15 @@
+package com.artifex.gsjava.callbacks;
+
+@FunctionalInterface
+public interface IStdInFunction {
+
+ /**
+ *
+ *
+ * @param callerHandle The caller handle.
+ * @param buf A string.
+ * @param len The number of bytes to read.
+ * @return The number of bytes read, must be <code>len</code>/
+ */
+ public int onStdIn(long callerHandle, byte[] buf, int len);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdOutFunction.java b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdOutFunction.java
new file mode 100644
index 00000000..c3635f54
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/callbacks/IStdOutFunction.java
@@ -0,0 +1,16 @@
+package com.artifex.gsjava.callbacks;
+
+@FunctionalInterface
+public interface IStdOutFunction {
+
+ /**
+ * Called when something should be written to the standard
+ * output stream.
+ *
+ * @param callerHandle The caller handle.
+ * @param str The string to write.
+ * @param len The number of bytes to write.
+ * @return The number of bytes written, must be <code>len</code>.
+ */
+ public int onStdOut(long callerHandle, byte[] str, int len);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/BMPDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/BMPDevice.java
new file mode 100644
index 00000000..2af8e7f1
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/BMPDevice.java
@@ -0,0 +1,18 @@
+package com.artifex.gsjava.devices;
+
+public class BMPDevice extends FileDevice {
+
+ public static final String BMPMONO = "bmpmono";
+ public static final String BMPGRAY = "bmpgray";
+ public static final String BMPSEP1 = "bmpsep1";
+ public static final String BMPSEP8 = "bmpsep8";
+ public static final String BMP16 = "bmp16";
+ public static final String BMP256 = "bmp256";
+ public static final String BMP16M = "bmp16m";
+ public static final String BMP32B = "bmp32b";
+
+ public BMPDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/Device.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/Device.java
new file mode 100644
index 00000000..74dc5332
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/Device.java
@@ -0,0 +1,308 @@
+package com.artifex.gsjava.devices;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+import java.awt.Dimension;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import com.artifex.gsjava.GSInstance;
+import com.artifex.gsjava.callbacks.IStdErrFunction;
+import com.artifex.gsjava.callbacks.IStdInFunction;
+import com.artifex.gsjava.callbacks.IStdOutFunction;
+import com.artifex.gsjava.util.Reference;
+
+/**
+ * <p>The <code>Device</code> class allows easier rendering to a Ghostscript device.
+ * The class allows setting different device parameters, running a file, and some
+ * safety with regard to Ghostcript instances. There can only be one instance of a
+ * <code>Device</code> at a time.</p>
+ *
+ * <p>Full documentation on each device can be found on the
+ * <a href=https://ghostscript.com/doc/current/Devices.htm>Details of Ghostscript Output Devices</a>
+ * webpage.</p>
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public abstract class Device {
+
+ private static Device activeDevice; // The active device, only one device may exist at a time
+
+ private GSInstance instance;
+ private final String deviceName;
+
+ /**
+ * Creates a new device with the given device name. When this constructor is called,
+ * an instance of Ghostscript cannot exist or an exception will be thrown. The check of
+ * whether an instance already exists does not include instances directly created
+ * through <code>GSAPI.gsapi_new_instance</code>.
+ *
+ * @param deviceName The name of the Ghostscript device.
+ * @throws DeviceNotSupportedException When <code>deviceName</code> is not a supported
+ * Ghostscript device.
+ * @throws DeviceInUseException When a <code>Device</code> object already exists.
+ * @throws IllegalStateException When an instance of Ghostscript created through <code>GSInstance</code>
+ * already exists.
+ */
+ public Device(String deviceName) throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ if (activeDevice != null)
+ throw new DeviceInUseException(activeDevice);
+ GSInstance instance = new GSInstance();
+ this.deviceName = Objects.requireNonNull(deviceName, "device name must be non-null");
+ StdIO io = new StdIO();
+ instance.set_stdio(io, io, io);
+ instance.init_with_args(new String[] {
+ "gs",
+ "-h",
+ });
+ instance.exit();
+ instance.delete_instance();
+ if (!io.hasDevice)
+ throw new DeviceNotSupportedException(deviceName);
+ }
+
+ /**
+ * Initializes the device on an instance with the given arguments. The
+ * given instance must not have had <code>init_with_args</code> called.
+ *
+ * @param instance The instance to initialize.
+ * @param more Arguments which should be passed to Ghostscript through
+ * <code>gsapi_init_with_args</code>.
+ */
+ public void initWithInstance(GSInstance instance, String... more) {
+ if (this.instance != null)
+ throw new IllegalStateException("instance has already been initialized");
+ this.instance = Objects.requireNonNull(instance, "Instance must be non-null");
+ List<String> args = new ArrayList<>(2 + more.length);
+ args.add("gs");
+ args.add("-sDEVICE=" + deviceName);
+ for (String s : more) {
+ args.add(s);
+ }
+ instance.init_with_args(args);
+ }
+
+ /**
+ * Runs a file.
+ *
+ * @param file The file to run.
+ * @param userErrors The user errors.
+ * @param pExitCode The exit code.
+ * @return The result of the <code>run_file</code>.
+ */
+ public int runFile(File file, int userErrors, Reference<Integer> pExitCode) {
+ return runFile(file.getAbsolutePath(), userErrors, pExitCode);
+ }
+
+ /**
+ * Runs a file.
+ *
+ * @param file The file to run.
+ * @param userErrors The user errors.
+ * @param pExitCode The exit code.
+ * @return The result of the <code>run_file</code>.
+ */
+ public int runFile(String filename, int userErrors, Reference<Integer> pExitCode) {
+ return instance.run_file(filename, userErrors, pExitCode);
+ }
+
+ /**
+ * Returns the internal device name. This name is the same as the one provided
+ * by the user in the Device constructor.
+ *
+ * @return The internal device name.
+ */
+ public String getInternalName() {
+ return deviceName;
+ }
+
+ /**
+ * Destroys this device.
+ *
+ * @throws IllegalStateException When the instance of Ghostscript fails to
+ * exit.
+ */
+ public void destroyDevice() throws IllegalStateException {
+ int code = instance.exit();
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to exit");
+ instance.delete_instance();
+ activeDevice = null;
+ }
+
+ /**
+ * Sets a device parameter.
+ *
+ * @param param The name of the device parameter.
+ * @param value The value to set the device parameter to.
+ * @param paramType The type of the device parameter.
+ * @return The result of setting the parameter through
+ * <code>gsapi_set_param</code>.
+ */
+ public int setParam(String param, Object value, int paramType) {
+ return instance.set_param(param, value, paramType);
+ }
+
+ /**
+ * Sets a string device parameter.
+ *
+ * @param param The name of the device parameter.
+ * @param value The string value to set the device parameter to.
+ * @param paramType The type of the device parameter.
+ * @return The result of setting the parameter through
+ * <code>gsapi_set_param</code>.
+ */
+ public int setParam(String param, String value, int paramType) {
+ return instance.set_param(param, value, paramType);
+ }
+
+ public int setResolution(Dimension resolution) {
+ return setResolution("[" + resolution.width + " " + resolution.height + "]");
+ }
+
+ public int setResolution(int resolution) {
+ return setResolution("[" + resolution + " " + resolution + "]");
+ }
+
+ public int setResolution(String resolution) {
+ return setParam("HWResolution", resolution, GS_SPT_PARSED);
+ }
+
+ public int setColorScreen(boolean state) {
+ return setParam("COLORSCREEN", state, GS_SPT_BOOL);
+ }
+
+ public int setDitherPPI(int lpi) {
+ return setParam("DITHERPPI", lpi, GS_SPT_INT);
+ }
+
+ public int setInterpolateControl(int controlValue) {
+ return setParam("InterpolateControl", controlValue, GS_SPT_INT);
+ }
+
+ public int setTextAlphaBits(int value) {
+ return setParam("TextAlphaBits", value, GS_SPT_INT);
+ }
+
+ public int setGraphicsAlphaBits(int value) {
+ return setParam("GraphicsAlphaBits", value, GS_SPT_INT);
+ }
+
+ public int setAlignToPixels(int n) {
+ return setParam("AlignToPixels", n, GS_SPT_INT);
+ }
+
+ public int setGridFitTT(int n) {
+ return setParam("GridFitTT", n, GS_SPT_INT);
+ }
+
+ public int setFirstPage(int page) {
+ return setParam("FirstPage", page, GS_SPT_INT);
+ }
+
+ public int setLastPage(int page) {
+ return setParam("LastPage", page, GS_SPT_INT);
+ }
+
+ public int setPageList(String list) {
+ return setParam("PageList", list, GS_SPT_PARSED);
+ }
+
+ public int setORIENT1(boolean state) {
+ return setParam("ORIENT1", state, GS_SPT_BOOL);
+ }
+
+ public int setDeviceWidthPoints(int w) {
+ return setParam("DEVICEWIDTHPOINTS", w, GS_SPT_INT);
+ }
+
+ public int setDeviceHeightPoints(int h) {
+ return setParam("DEVICEHEIGHTPOINTS", h, GS_SPT_INT);
+ }
+
+ public int setDefaultPaperSize(String paperSize) {
+ return setParam("DEFAULTPAPERSIZE", paperSize, GS_SPT_STRING);
+ }
+
+ public int setFontMap(String files) {
+ return setParam("FONTMAP", files, GS_SPT_PARSED);
+ }
+
+ public int setFontPath(String paths) {
+ return setParam("FONTPATH", paths, GS_SPT_PARSED);
+ }
+
+ public int setSubstFont(String fontname) {
+ return setParam("SUBSTFONT", fontname, GS_SPT_STRING);
+ }
+
+ public int setGenericResourceDir(String path) {
+ return setParam("FontResourceDir", path, GS_SPT_STRING);
+ }
+
+ public int setStdout(String filename) {
+ return setParam("stdout", filename, GS_SPT_STRING);
+ }
+
+ /**
+ * Returns the stored Ghostscript instance.
+ *
+ * @return The instance.
+ */
+ protected final GSInstance getInstance() {
+ return instance;
+ }
+
+ protected final String toArrayParameter(String[] array) {
+ StringBuilder builder = new StringBuilder();
+ if (array.length > 0) {
+ builder.append(array[0]);
+ for (int i = 1; i < array.length; i++) {
+ builder.append(',');
+ builder.append(array[i]);
+ }
+ }
+ return builder.toString();
+ }
+
+ protected final String toArrayParameter(List<String> list) {
+ return toArrayParameter(list.toArray(new String[list.size()]));
+ }
+
+ @Override
+ public String toString() {
+ return "Device[instance=" + instance + ",deviceName=" + deviceName + "]";
+ }
+
+ private class StdIO implements IStdInFunction, IStdOutFunction, IStdErrFunction {
+
+ private boolean hasDevice;
+
+ @Override
+ public int onStdIn(long callerHandle, byte[] buf, int len) {
+ return buf.length;
+ }
+
+ @Override
+ public int onStdOut(long callerHandle, byte[] str, int len) {
+ if (!hasDevice) {
+ String outp = new String(str);
+ hasDevice = outp.contains(deviceName);
+ }
+ return str.length;
+ }
+
+ @Override
+ public int onStdErr(long callerHandle, byte[] str, int len) {
+ if (!hasDevice) {
+ String outp = new String(str);
+ hasDevice = outp.contains(deviceName);
+ }
+ return str.length;
+ }
+
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceInUseException.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceInUseException.java
new file mode 100644
index 00000000..aa5621fc
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceInUseException.java
@@ -0,0 +1,17 @@
+package com.artifex.gsjava.devices;
+
+public class DeviceInUseException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private Device device;
+
+ public DeviceInUseException(Device device) {
+ super(device == null ? "null" : device.toString());
+ this.device = device;
+ }
+
+ public Device getDevice() {
+ return device;
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceNotSupportedException.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceNotSupportedException.java
new file mode 100644
index 00000000..453fdead
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/DeviceNotSupportedException.java
@@ -0,0 +1,28 @@
+package com.artifex.gsjava.devices;
+
+public class DeviceNotSupportedException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public DeviceNotSupportedException() {
+ super();
+ }
+
+ public DeviceNotSupportedException(String message) {
+ super(message);
+ }
+
+ public DeviceNotSupportedException(Throwable cause) {
+ super(cause);
+ }
+
+ public DeviceNotSupportedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected DeviceNotSupportedException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/DisplayDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/DisplayDevice.java
new file mode 100644
index 00000000..959ed4d8
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/DisplayDevice.java
@@ -0,0 +1,55 @@
+package com.artifex.gsjava.devices;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+import java.util.List;
+
+public class DisplayDevice extends Device {
+
+ public static final String X11 = "x11";
+ public static final String X11ALPHA = "x11alpha";
+ public static final String X11CMYK = "x11cmyk";
+ public static final String X11MONO = "x11mono";
+ public static final String X11GRAY2 = "x11gray2";
+ public static final String X11GRAY4 = "x11gray4";
+
+ public DisplayDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("display");
+ }
+
+ public DisplayDevice(String device) throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super(device);
+ }
+
+ public void setDisplayFormat(int format) {
+ setParam("DisplayFormat", format, GS_SPT_INT);
+ }
+
+ public void setDisplayResolution(int dpi) {
+ setParam("DisplayResolution", dpi, GS_SPT_INT);
+ }
+
+ public void setSeparationColorNames(String nameArray) {
+ setParam("SeparationColorNames", nameArray, GS_SPT_PARSED);
+ }
+
+ public void setSeparationColorNames(String[] names) {
+ setSeparationColorNames(toArrayParameter(names));
+ }
+
+ public void setSeparationColorNames(List<String> names) {
+ setSeparationColorNames(toArrayParameter(names));
+ }
+
+ public void setSeparationOrder(String orderArray) {
+ setParam("SeparationOrder", orderArray, GS_SPT_PARSED);
+ }
+
+ public void setSeparationOrder(String[] order) {
+ setSeparationOrder(toArrayParameter(order));
+ }
+
+ public void setSeparationOrder(List<String> order) {
+ setSeparationOrder(toArrayParameter(order));
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/EPSDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/EPSDevice.java
new file mode 100644
index 00000000..efa999a1
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/EPSDevice.java
@@ -0,0 +1,9 @@
+package com.artifex.gsjava.devices;
+
+public class EPSDevice extends PostScriptDevice {
+
+ public EPSDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("eps2write");
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/FAXDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/FAXDevice.java
new file mode 100644
index 00000000..5770a8b4
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/FAXDevice.java
@@ -0,0 +1,18 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class FAXDevice extends FileDevice {
+
+ public static final String FAXG3 = "faxg3";
+ public static final String FAXG32D = "faxg32d";
+ public static final String FAXG4 = "faxg4";
+
+ public FAXDevice(String device) throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super(device);
+ }
+
+ public void setMinFeatureSize(int value) {
+ setParam("MinFeatureSize", value, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/FileDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/FileDevice.java
new file mode 100644
index 00000000..9f3d6ce3
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/FileDevice.java
@@ -0,0 +1,36 @@
+package com.artifex.gsjava.devices;
+
+import java.io.File;
+
+import com.artifex.gsjava.GSAPI;
+import com.artifex.gsjava.GSInstance;
+
+public abstract class FileDevice extends Device {
+
+ public FileDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+ public void initFileWithInstance(GSInstance instance, File file, String... more) {
+ initFileWithInstance(instance, file, more);
+ }
+
+ public void setOutputFile(File file) {
+ setOutputFile(file.getAbsolutePath());
+ }
+
+ public void setOutputFile(String file) {
+ setParam("OutputFile", file, GSAPI.GS_SPT_STRING);
+ }
+
+ public void initFileWithInstance(GSInstance instance, String file, String... more) {
+ String[] args = new String[2 + more.length];
+ args[0] = "-o";
+ args[1] = file;
+ for (int i = 0; i < more.length; i++) {
+ args[i + 2] = more[i];
+ }
+ initWithInstance(instance, args);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/HighLevelDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/HighLevelDevice.java
new file mode 100644
index 00000000..4a08d522
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/HighLevelDevice.java
@@ -0,0 +1,13 @@
+package com.artifex.gsjava.devices;
+
+/**
+ * Interface indicating a device is a high-level device.
+ * See <a href=https://ghostscript.com/doc/current/VectorDevices.htm>High Level Output Devices</a>
+ * webpage for full documentation on each device.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public interface HighLevelDevice {
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/JPEGDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/JPEGDevice.java
new file mode 100644
index 00000000..bf015349
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/JPEGDevice.java
@@ -0,0 +1,19 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class JPEGDevice extends FileDevice {
+
+ public JPEGDevice()
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super("jpeg");
+ }
+
+ public void setJPEGQuality(int quality) {
+ setParam("JPEGQ", quality, GSAPI.GS_SPT_INT);
+ }
+
+ public void setQualityFactor(float scale) {
+ setParam("QFactor", scale, GSAPI.GS_SPT_FLOAT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/OCRDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/OCRDevice.java
new file mode 100644
index 00000000..533714bf
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/OCRDevice.java
@@ -0,0 +1,24 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class OCRDevice extends FileDevice {
+
+ public static final int DEFAULT_ENGINE = 0;
+ public static final int LSTM_ENGINE = 1;
+ public static final int TESSERACT_ENGINE = 2;
+ public static final int LSTM_AND_TESSERACT_ENGINE = 3;
+
+ public OCRDevice()
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super("ocr");
+ }
+
+ public void setOCRLanguage(String language) {
+ setParam("OCRLanguage", language, GSAPI.GS_SPT_PARSED);
+ }
+
+ public void setOCREngine(int engine) {
+ setParam("OCREngine", engine, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PCXDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PCXDevice.java
new file mode 100644
index 00000000..c0323e60
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PCXDevice.java
@@ -0,0 +1,17 @@
+package com.artifex.gsjava.devices;
+
+public class PCXDevice extends FileDevice {
+
+ public static final String PCXMONO = "pcxmono";
+ public static final String PCXGRAY = "pcxgray";
+ public static final String PCX16 = "pcx16";
+ public static final String PCX256 = "pcx256";
+ public static final String PCX24B = "pcx24b";
+ public static final String PCXCMYK = "pcxcmyk";
+
+ public PCXDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFDevice.java
new file mode 100644
index 00000000..2d084f71
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFDevice.java
@@ -0,0 +1,90 @@
+package com.artifex.gsjava.devices;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+public class PDFDevice extends PDFPostscriptDeviceFamily {
+
+ public PDFDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("pdfwrite");
+ }
+
+ public void setMaxInlineImageSize(int value) {
+ setParam("MaxInlineImageSize", value, GS_SPT_INT);
+ }
+
+ public void setDoNumCopies(boolean state) {
+ setParam("DoNumCopies", state, GS_SPT_BOOL);
+ }
+
+ public void setDetectDuplicateImages(boolean state) {
+ setParam("DetectDuplicateImages", state, GS_SPT_BOOL);
+ }
+
+ public void setFastWebView(boolean state) {
+ setParam("FastWebView", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveAnnots(boolean state) {
+ setParam("PreserveAnnots", state, GS_SPT_BOOL);
+ }
+
+ public void setPatternImagemask(boolean state) {
+ setParam("PatternImagemask", state, GS_SPT_BOOL);
+ }
+
+ public void setMaxClipPathSize(int value) {
+ setParam("MaxClipPathSize", value, GS_SPT_INT);
+ }
+
+ public void setMaxShadingBitmapSize(int value) {
+ setParam("MaxShadingBitmapSize", value, GS_SPT_INT);
+ }
+
+ public void setHaveTrueTypes(boolean state) {
+ setParam("HaveTrueTypes", state, GS_SPT_BOOL);
+ }
+
+ public void setHaveTransparency(boolean state) {
+ setParam("HaveTransparency", state, GS_SPT_BOOL);
+ }
+
+ public void setPDFX(boolean state) {
+ setParam("PDFX", state, GS_SPT_BOOL);
+ }
+
+ public void setOwnerPassword(String value) {
+ setParam("OwnerPassword", value, GS_SPT_STRING);
+ }
+
+ public void setUserPassword(String value) {
+ setParam("UserPassword", value, GS_SPT_STRING);
+ }
+
+ public void setPermissions(int value) {
+ setParam("Permissions", value, GS_SPT_INT);
+ }
+
+ public void setEncryptionR(int num) {
+ setParam("EncryptionR", num, GS_SPT_INT);
+ }
+
+ public void setKeyLength(int length) {
+ setParam("KeyLength", length, GS_SPT_INT);
+ }
+
+ public void setDocumentUUID(String value) {
+ setParam("DocumentUUID", value, GS_SPT_STRING);
+ }
+
+ public void setInstanceUUID(String value) {
+ setParam("InstanceUUID", value, GS_SPT_STRING);
+ }
+
+ public void setDocumentTimeSeq(int value) {
+ setParam("DocumentTimeSeq", value, GS_SPT_INT);
+ }
+
+ public void setDSCEncoding(String encoding) {
+ setParam("DSCEncoding", encoding, GS_SPT_STRING);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFImageDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFImageDevice.java
new file mode 100644
index 00000000..8eedbab9
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFImageDevice.java
@@ -0,0 +1,19 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class PDFImageDevice extends FileDevice {
+
+ public static final String PDFIMAGE8 = "pdfimage8";
+ public static final String PDFIMAGE24 = "pdfimage24";
+ public static final String PDFIMAGE32 = "pdfimage32";
+
+ public PDFImageDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+ public void setDownScaleFactor(int factor) {
+ setParam("DownScaleFactor", factor, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFPostscriptDeviceFamily.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFPostscriptDeviceFamily.java
new file mode 100644
index 00000000..6afc997c
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PDFPostscriptDeviceFamily.java
@@ -0,0 +1,340 @@
+package com.artifex.gsjava.devices;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+/**
+ * This class is the root device containing methods to set parameters defined
+ * in section 6.1 in the
+ * <a href="https://ghostscript.com/doc/current/VectorDevices.htm">Vector Devices</a>
+ * documentation.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public abstract class PDFPostscriptDeviceFamily extends FileDevice implements HighLevelDevice {
+
+ public PDFPostscriptDeviceFamily(String device)
+ throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super(device);
+ }
+
+ public void setCompressFonts(boolean state) {
+ setParam("CompressFonts", state, GS_SPT_BOOL);
+ }
+
+ public void setCompressStreams(boolean state) {
+ setParam("CompressStreas", state, GS_SPT_BOOL);
+ }
+
+ public void setAlwaysEmbed(String value) {
+ setParam("AlwaysEmbed", value, GS_SPT_PARSED);
+ }
+
+ public void setAntiAliasColorImages(boolean state) {
+ setParam("AntiAliasColorImages", state, GS_SPT_BOOL);
+ }
+
+ public void setAntiAliasGrayImages(boolean state) {
+ setParam("AntiAliasGrayImages", state, GS_SPT_BOOL);
+ }
+
+ public void setAntiAliasMonoImages(boolean state) {
+ setParam("AntiAliasMonoImages", state, GS_SPT_BOOL);
+ }
+
+ public void setASCII85EncodePages(boolean state) {
+ setParam("ASCII85EncodePages", state, GS_SPT_BOOL);
+ }
+
+ public void setAutoFilterColorImages(boolean state) {
+ setParam("AutoFilterColorImages", state, GS_SPT_BOOL);
+ }
+
+ public void setAutoFilterGrayImages(boolean state) {
+ setParam("AutoFilterGrayImages", state, GS_SPT_BOOL);
+ }
+
+ public void setAutoPositionEPSFiles(boolean state) {
+ setParam("AutoPositionEPSFiles", state, GS_SPT_BOOL);
+ }
+
+ public void setAutoRotatePages(String mode) {
+ setParam("AutoRotatePages", mode, GS_SPT_STRING);
+ }
+
+ public void setBinding(String mode) {
+ setParam("Binding", mode, GS_SPT_STRING);
+ }
+
+ public void setCalCMYKProfile(String profile) {
+ setParam("CalCMYKProfile", profile, GS_SPT_PARSED);
+ }
+
+ public void setCalGrayProfile(String profile) {
+ setParam("CalGrayProfile", profile, GS_SPT_PARSED);
+ }
+
+ public void setCalRGBProfile(String profile) {
+ setParam("CalRGBProfile", profile, GS_SPT_PARSED);
+ }
+
+ public void setCannotEmbedFontPolicy(String mode) {
+ setParam("CannotEmbedFontPolicy", mode, GS_SPT_STRING);
+ }
+
+ public void setColorACSImageDict(String dict) {
+ setParam("ColorACSImageDict", dict, GS_SPT_PARSED);
+ }
+
+ public void setColorConversionStrategy(String strat) {
+ setParam("ColorConversionSrategy", strat, GS_SPT_STRING);
+ }
+
+ public void setColorImageDepth(int value) {
+ setParam("ColorImageDepth", value, GS_SPT_INT);
+ }
+
+ public void setColorImageDict(String dict) {
+ setParam("ColorImageDict", dict, GS_SPT_PARSED);
+ }
+
+ public void setColorImageFilter(String filter) {
+ setParam("ColorImageFilter", filter, GS_SPT_STRING);
+ }
+
+ public void setColorImageDownscaleThreshold(float value) {
+ setParam("ColorImageDownscaleThreshold", value, GS_SPT_FLOAT);
+ }
+
+ public void setColorImageDownsampleType(String type) {
+ setParam("ColorImageDownsampleType", type, GS_SPT_STRING);
+ }
+
+ public void setColorImageResolution(int value) {
+ setParam("ColorImageResolution", value, GS_SPT_INT);
+ }
+
+ public void setCompatabilityLevel(String level) {
+ setParam("CompatabilityLevel", level, GS_SPT_PARSED);
+ }
+
+ public void setCompressPages(boolean state) {
+ setParam("CompressPages", state, GS_SPT_BOOL);
+ }
+
+ public void setConvertCMYKImagesToRGB(boolean state) {
+ setParam("ConvertCMYKImagesToRGB", state, GS_SPT_BOOL);
+ }
+
+ public void setConvertColorImagesToIndexed(boolean state) {
+ setParam("ConvertColorImagesToIndexed", state, GS_SPT_BOOL);
+ }
+
+ public void setCoreDictVersion(int version) {
+ setParam("CoreDictVersion", version, GS_SPT_INT);
+ }
+
+ public void setCreateJobTicket(boolean state) {
+ setParam("CreateJobTicket", state, GS_SPT_BOOL);
+ }
+
+ public void setDefaultRenderingIntent(String intent) {
+ setParam("DefaultRenderingIntent", intent, GS_SPT_STRING);
+ }
+
+ public void setDetectBlends(boolean state) {
+ setParam("DetectBlends", state, GS_SPT_BOOL);
+ }
+
+ public void setDoThumbnails(boolean state) {
+ setParam("DoThumbnails", state, GS_SPT_BOOL);
+ }
+
+ public void setDownsampleColorImages(boolean state) {
+ setParam("DownsampleColorImages", state, GS_SPT_BOOL);
+ }
+
+ public void setDownsampleGrayImages(boolean state) {
+ setParam("DownsampleGrayImages", state, GS_SPT_BOOL);
+ }
+
+ public void setDownsampleMonoImages(boolean state) {
+ setParam("DownsampleMonoImages", state, GS_SPT_BOOL);
+ }
+
+ public void setEmbedAllFonts(boolean state) {
+ setParam("EmbedAllFonts", state, GS_SPT_BOOL);
+ }
+
+ public void setEmitDSCWarnings(boolean state) {
+ setParam("EmitDSCWarnings", state, GS_SPT_BOOL);
+ }
+
+ public void setEncodeColorImages(boolean state) {
+ setParam("EncodeColorImages", state, GS_SPT_BOOL);
+ }
+
+ public void setEncodeGrayImages(boolean state) {
+ setParam("EncodeGrayImages", state, GS_SPT_BOOL);
+ }
+
+ public void setEncodeMonoImages(boolean state) {
+ setParam("EncodeMonoImages", state, GS_SPT_BOOL);
+ }
+
+ public void setEndPage(int page) {
+ setParam("EndPage", page, GS_SPT_INT);
+ }
+
+ public void setGrayACSImageDict(String dict) {
+ setParam("GrayACSImageDict", dict, GS_SPT_PARSED);
+ }
+
+ public void setGrayImageDepth(int value) {
+ setParam("GrayImageDepth", value, GS_SPT_INT);
+ }
+
+ public void setGrayImageDict(String dict) {
+ setParam("GrayImageDict", dict, GS_SPT_PARSED);
+ }
+
+ public void setGrayImageDownsampleThreshold(float thresh) {
+ setParam("GrayImageDownsampleThreshold", thresh, GS_SPT_FLOAT);
+ }
+
+ public void setGrayImageDownsampleType(String type) {
+ setParam("GrayImageDownsampleType", type, GS_SPT_STRING);
+ }
+
+ public void setGrayImageFilter(String filter) {
+ setParam("GrayImageFilter", filter, GS_SPT_STRING);
+ }
+
+ public void setGrayImageResolution(int resolution) {
+ setParam("GrayImageResolution", resolution, GS_SPT_INT);
+ }
+
+ public void setImageMemory(long memory) {
+ setParam("ImageMemory", memory, GS_SPT_SIZE_T);
+ }
+
+ public void setLockDistillerParams(boolean state) {
+ setParam("LockDistillerParams", state, GS_SPT_BOOL);
+ }
+
+ public void setLZWEncodePages(boolean state) {
+ setParam("LZWEncodePages", state, GS_SPT_BOOL);
+ }
+
+ public void setMaxSubsetPct(int value) {
+ setParam("MaxSubsetPct", value, GS_SPT_INT);
+ }
+
+ public void setMonoImageDepth(int depth) {
+ setParam("MonoImageDepth", depth, GS_SPT_INT);
+ }
+
+ public void setMonoImageDict(String dict) {
+ setParam("MonoImageDict", dict, GS_SPT_PARSED);
+ }
+
+ public void setMonoImageDownsampleThreshold(float thresh) {
+ setParam("MonoImageDownsampleThreshold", thresh, GS_SPT_FLOAT);
+ }
+
+ public void setMonoImageDownsampleType(String type) {
+ setParam("MonoImageDownsampleType", type, GS_SPT_STRING);
+ }
+
+ public void setMonoImageFilter(String filter) {
+ setParam("MonoImageFilter", filter, GS_SPT_STRING);
+ }
+
+ public void setMonoImageResolution(int resolution) {
+ setParam("MonoImageResolution", resolution, GS_SPT_INT);
+ }
+
+ public void setNeverEmbed(String value) {
+ setParam("NeverEmbed", value, GS_SPT_PARSED);
+ }
+
+ public void setOffOptimizations(int value) {
+ setParam("OffOptimizations", value, GS_SPT_INT);
+ }
+
+ public void setOPM(int value) {
+ setParam("OPM", value, GS_SPT_INT);
+ }
+
+ public void setOptimize(boolean state) {
+ setParam("Optimize", state, GS_SPT_BOOL);
+ }
+
+ public void setParseDSCComments(boolean state) {
+ setParam("ParseDSCComments", state, GS_SPT_BOOL);
+ }
+
+ public void setParseDSCCommentsForDocInfo(boolean state) {
+ setParam("ParseDSCCommentsForDocInfo", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveCopyPage(boolean state) {
+ setParam("PreserveCopyPage", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveEPSInfo(boolean state) {
+ setParam("PreserveEPSInfo", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveHalftoneInfo(boolean state) {
+ setParam("PreserveHalftoneInfo", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveOPIComments(boolean state) {
+ setParam("PreserveOPIComments", state, GS_SPT_BOOL);
+ }
+
+ public void setPreserveOverprintSettings(boolean state) {
+ setParam("PreserveOverprintSettings", state, GS_SPT_BOOL);
+ }
+
+ public void setsRGBProfile(String profile) {
+ setParam("sRGBProfile", profile, GS_SPT_PARSED);
+ }
+
+ public void setStartPage(int page) {
+ setParam("StartPage", page, GS_SPT_INT);
+ }
+
+ public void setSubsetFonts(boolean state) {
+ setParam("SubsetFonts", state, GS_SPT_BOOL);
+ }
+
+ public void setTransferFunctionInfo(String info) {
+ setParam("TransferFunctionInfo", info, GS_SPT_STRING);
+ }
+
+ public void setUCRandBGInfo(String info) {
+ setParam("UCRandBGInfo", info, GS_SPT_STRING);
+ }
+
+ public void setUseFlateCompression(boolean state) {
+ setParam("UseFlateCompression", state, GS_SPT_BOOL);
+ }
+
+ public void setUsePrologue(boolean state) {
+ setParam("UsePrologue", state, GS_SPT_BOOL);
+ }
+
+ public void setPassThroughJPEGImages(boolean state) {
+ setParam("PassThroughJPEGImages", state, GS_SPT_BOOL);
+ }
+
+ // Specific to PostScript and PDF input
+
+ public void setPDFSETTINGS(String config) {
+ setParam("PDFSETTINGS", config, GS_SPT_STRING);
+ }
+
+ // Specific to PCL and PXL input
+} \ No newline at end of file
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PNGDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PNGDevice.java
new file mode 100644
index 00000000..8f291851
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PNGDevice.java
@@ -0,0 +1,36 @@
+package com.artifex.gsjava.devices;
+
+import java.awt.Color;
+
+import com.artifex.gsjava.GSAPI;
+
+public class PNGDevice extends FileDevice {
+
+ public static final String PNG256 = "png256";
+ public static final String PNG16 = "png16";
+ public static final String PNGMONO = "pngmono";
+ public static final String PNGMONOD = "pngmonod";
+ public static final String PNG16M = "png16m";
+ public static final String PNGGRAY = "pnggray";
+ public static final String PNGALPHA = "pngalpha";
+
+ public PNGDevice(String format) throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(format);
+ }
+
+ public void setDownScaleFactor(int value) {
+ setParam("DownScaleFactor", value, GSAPI.GS_SPT_INT);
+ }
+
+ public void setMinFeatureSize(int state) {
+ setParam("MinFeatureSize", state, GSAPI.GS_SPT_INT);
+ }
+
+ public void setBackgroundColor(Color color) {
+ setBackgroundColor(color.getRGB());
+ }
+
+ public void setBackgroundColor(int color) {
+ setParam("BackgroundColor", color, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PNMDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PNMDevice.java
new file mode 100644
index 00000000..14474906
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PNMDevice.java
@@ -0,0 +1,25 @@
+package com.artifex.gsjava.devices;
+
+public class PNMDevice extends FileDevice {
+
+ public static final String PBM = "pbm";
+ public static final String PBMRAW = "pbmraw";
+ public static final String PGM = "pbm";
+ public static final String PGMRAW = "pgmraw";
+ public static final String PGMN = "pgnm";
+ public static final String PGMNRAW = "pgnmraw";
+ public static final String PNM = "pnm";
+ public static final String PNMRAW = "pnmraw";
+ public static final String PPM = "ppm";
+ public static final String PPMRAW = "ppmraw";
+ public static final String PKM = "pkm";
+ public static final String PKMRAW = "pkmraw";
+ public static final String PKSM = "pksm";
+ public static final String PKSMRAW = "pksmraw";
+
+ public PNMDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PSDDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PSDDevice.java
new file mode 100644
index 00000000..312af85d
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PSDDevice.java
@@ -0,0 +1,17 @@
+package com.artifex.gsjava.devices;
+
+public class PSDDevice extends FileDevice {
+
+ public static final String PSDCMYK = "psdcmyk";
+ public static final String PSDRGB = "psdrgb";
+ public static final String PSDCMYK16 = "psdcmyk16";
+ public static final String PSDRGB16 = "psdrgb16";
+ public static final String PSDCMYKOG = "psdcmykog";
+
+ public PSDDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+ // Missing device parameters
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PXLDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PXLDevice.java
new file mode 100644
index 00000000..9fb55fd2
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PXLDevice.java
@@ -0,0 +1,17 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class PXLDevice extends FileDevice implements HighLevelDevice {
+
+ public static final String PXLMONO = "pxlmono";
+ public static final String PXLCOLOR = "pxlcolor";
+
+ public PXLDevice(String device) throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super(device);
+ }
+
+ public void setCompressMode(int mode) {
+ setParam("CompressMode", mode, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/PostScriptDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/PostScriptDevice.java
new file mode 100644
index 00000000..3926ebf9
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/PostScriptDevice.java
@@ -0,0 +1,59 @@
+package com.artifex.gsjava.devices;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+public class PostScriptDevice extends PDFPostscriptDeviceFamily {
+
+ public PostScriptDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("ps2write");
+ }
+
+ /**
+ * Intended to be an internal way to override the normal
+ * ps2write device.
+ *
+ * @param override The device override name.
+ * @throws IllegalStateException {@link Device#Device(String)}
+ * @throws DeviceNotSupportedException {@link Device#Device(String)}
+ * @throws DeviceInUseException {@link Device#Device(String)}
+ */
+ protected PostScriptDevice(String override) throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super(override);
+ }
+
+// public void setPSDocOptions(String options) {
+// setParam("PSDocOptions", options, GS_SPT_STRING);
+// }
+//
+// public void setPSPageOptions(String[] options) {
+//
+// }
+//
+// public void setPSPageOptions(List<String> options) {
+// setPSPageOptions(options.toArray(new String[options.size()]));
+// }
+
+ public void setProduceDSC(boolean state) {
+ setParam("ProduceDSC", state, GS_SPT_BOOL);
+ }
+
+ public void setCompressEntireFile(boolean state) {
+ setParam("CompressEntireFile", state, GS_SPT_BOOL);
+ }
+
+ public void setRotatePages(boolean state) {
+ setParam("RotatePages", state, GS_SPT_BOOL);
+ }
+
+ public void setCenterPages(boolean state) {
+ setParam("CenterPages", state, GS_SPT_BOOL);
+ }
+
+ public void setSetPageSize(boolean state) {
+ setParam("SetPageSize", state, GS_SPT_BOOL);
+ }
+
+ public void setDoNumCopies(boolean state) {
+ setParam("DoNumCopies", state, GS_SPT_BOOL);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/TIFFDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/TIFFDevice.java
new file mode 100644
index 00000000..25b9d335
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/TIFFDevice.java
@@ -0,0 +1,80 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class TIFFDevice extends FileDevice {
+
+ public static final String TIFFGRAY = "tiffgray";
+ public static final String TIFF12NC = "tiff12nc";
+ public static final String TIFF24NC = "tiff24nc";
+ public static final String TIFF48NC = "tiff48nc";
+ public static final String TIFF32NC = "tiff32nc";
+ public static final String TIFF64NC = "tiff64nc";
+ public static final String TIFFSEP = "tiffsep";
+
+ public static final String TIFFSEP1 = "tiffsep1";
+ public static final String TIFFSCALED = "tiffscaled";
+ public static final String TIFFSCALED4 = "tiffscaled4";
+ public static final String TIFFSCALED8 = "tiffscaled8";
+ public static final String TIFFSCALED24 = "tiffscaled24";
+ public static final String TIFFSCALED32 = "tiffscaled32";
+
+ public static final String TIFFCRLE = "tiffcrle";
+ public static final String TIFFG3 = "tiffg3";
+ public static final String TIFFG32D = "tiffg32d";
+ public static final String TIFFG4 = "tiffg4";
+ public static final String TIFFLZW = "tifflzw";
+ public static final String TIFFPACK = "tiffpack";
+
+ public static final String NONE = "none";
+ public static final String CRLE = "crle";
+ public static final String G3 = "g3";
+ public static final String G4 = "g4";
+ public static final String LZW = "lzw";
+ public static final String PACK = "pack";
+
+ public TIFFDevice(String deviceName)
+ throws DeviceNotSupportedException, DeviceInUseException, IllegalStateException {
+ super(deviceName);
+ }
+
+ public void setMaxStripSize(int size) {
+ setParam("MaxStripSize", size, GSAPI.GS_SPT_INT);
+ }
+
+ public void setFillOrder(int order) {
+ setParam("FillOrder", order, GSAPI.GS_SPT_INT);
+ }
+
+ public void setUseBigTIFF(boolean state) {
+ setParam("UseBigTIFF", state, GSAPI.GS_SPT_BOOL);
+ }
+
+ public void setTIFFDateTime(boolean state) {
+ setParam("TIFFDateTime", state, GSAPI.GS_SPT_BOOL);
+ }
+
+ public void setCompression(String compression) {
+ setParam("Compression", compression, GSAPI.GS_SPT_NAME);
+ }
+
+ public void setAdjustWith(int state) {
+ setParam("AdjustWidth", state, GSAPI.GS_SPT_INT);
+ }
+
+ public void setMinFeatureSize(int state) {
+ setParam("MinFeatureSize", state, GSAPI.GS_SPT_INT);
+ }
+
+ public void setDownScaleFactor(int factor) {
+ setParam("DownScaleFactor", factor, GSAPI.GS_SPT_INT);
+ }
+
+ public void setPostRenderProfile(String path) {
+ setParam("PostRenderProfile", path, GSAPI.GS_SPT_NAME);
+ }
+
+ public void setPrintSpotCMYK(boolean state) {
+ setParam("PrintSpotCMYK", state, GSAPI.GS_SPT_BOOL);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/TextDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/TextDevice.java
new file mode 100644
index 00000000..00f67f5a
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/TextDevice.java
@@ -0,0 +1,14 @@
+package com.artifex.gsjava.devices;
+
+import com.artifex.gsjava.GSAPI;
+
+public class TextDevice extends FileDevice implements HighLevelDevice {
+
+ public TextDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("txtwrite");
+ }
+
+ public void setTextFormat(int format) {
+ setParam("TextFormat", format, GSAPI.GS_SPT_INT);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/devices/XPSDevice.java b/demos/java/gsjava/src/com/artifex/gsjava/devices/XPSDevice.java
new file mode 100644
index 00000000..258dc014
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/devices/XPSDevice.java
@@ -0,0 +1,9 @@
+package com.artifex.gsjava.devices;
+
+public class XPSDevice extends FileDevice implements HighLevelDevice {
+
+ public XPSDevice() throws IllegalStateException, DeviceNotSupportedException, DeviceInUseException {
+ super("xpswrite");
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/AllocationError.java b/demos/java/gsjava/src/com/artifex/gsjava/util/AllocationError.java
new file mode 100644
index 00000000..d2f6c99f
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/AllocationError.java
@@ -0,0 +1,33 @@
+package com.artifex.gsjava.util;
+
+/**
+ * An error thrown when native memory allocation fails.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class AllocationError extends Error {
+
+ private static final long serialVersionUID = 1L;
+
+ public AllocationError() {
+ super();
+ }
+
+ public AllocationError(String message) {
+ super(message);
+ }
+
+ public AllocationError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AllocationError(Throwable cause) {
+ super(cause);
+ }
+
+ protected AllocationError(String message, Throwable cause,
+ boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/ByteArrayReference.java b/demos/java/gsjava/src/com/artifex/gsjava/util/ByteArrayReference.java
new file mode 100644
index 00000000..1638bb95
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/ByteArrayReference.java
@@ -0,0 +1,23 @@
+package com.artifex.gsjava.util;
+
+/**
+ * Stores a reference to a byte array.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class ByteArrayReference extends Reference<byte[]> {
+
+ public ByteArrayReference() {
+ super();
+ }
+
+ public ByteArrayReference(final byte[] value) {
+ super(value);
+ }
+
+ public String asString() {
+ byte[] val = getValue();
+ return val == null ? "null" : new String(val);
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/BytePointer.java b/demos/java/gsjava/src/com/artifex/gsjava/util/BytePointer.java
new file mode 100644
index 00000000..8b63254e
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/BytePointer.java
@@ -0,0 +1,68 @@
+package com.artifex.gsjava.util;
+
+/**
+ * A byte pointer stores a pointer to a memory location containing
+ * bytes.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class BytePointer extends NativePointer implements NativeArray<Byte> {
+
+ private long length;
+
+ public BytePointer() {
+ super();
+ this.length = 0;
+ }
+
+ @Override
+ public void allocate(long length) throws IllegalStateException, AllocationError {
+ calloc(length, BYTE_SIZE);
+ this.length = length;
+ }
+
+ @Override
+ public void set(long index, Byte value) throws IndexOutOfBoundsException, NullPointerException {
+ final long address = getAddress();
+ if (address == NULL)
+ throw new NullPointerException("address is null");
+ if (index < 0 || index >= length)
+ throw new IndexOutOfBoundsException(new StringBuilder().append("index: ").append(index).toString());
+ setByteNative(address, index, value);
+ }
+
+ @Override
+ public Byte at(long index) throws IndexOutOfBoundsException, NullPointerException {
+ final long address = getAddress();
+ if (address == NULL)
+ throw new NullPointerException("address is null");
+ if (index < 0 || index >= length)
+ throw new IndexOutOfBoundsException(new StringBuilder().append("index: ").append(index).toString());
+ return byteAtNative(address, index);
+ }
+
+ @Override
+ public Byte[] toArray() throws NullPointerException {
+ byte[] byteArray = (byte[])toArrayNoConvert();
+ Byte[] bArray = new Byte[byteArray.length];
+ int i = 0;
+ for (byte b : byteArray)
+ bArray[i++] = b;
+ return bArray;
+ }
+
+ @Override
+ public Object toArrayNoConvert() throws NullPointerException {
+ final long address = getAddress();
+ if (address == NULL)
+ throw new NullPointerException("address is null");
+ return byteArrayNative(address, length);
+ }
+
+ @Override
+ public long length() {
+ return length;
+ }
+
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/NativeArray.java b/demos/java/gsjava/src/com/artifex/gsjava/util/NativeArray.java
new file mode 100644
index 00000000..0ea059c1
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/NativeArray.java
@@ -0,0 +1,67 @@
+package com.artifex.gsjava.util;
+
+/**
+ * A NativeArray is an natively allocated array with a set length.
+ *
+ * @author Ethan Vrhel
+ *
+ * @param <T> The type stored in the array.
+ */
+public interface NativeArray<T> {
+
+ /**
+ * Allocates the array of length <code>length</code>.
+ *
+ * @param length The length of the array.
+ * @throws IllegalStateException When the memory has already been allocated.
+ * @throws AllocationError When the allocation fails.
+ */
+ public void allocate(long length) throws IllegalStateException, AllocationError;
+
+ /**
+ * Sets the value of an element in the array.
+ *
+ * @param index The index to set.
+ * @param value The value to set to.
+ * @throws IndexOutOfBoundsException When <code>index</code> is less than 0 or
+ * greater or equal to the length.
+ * @throws NullPointerException When the array has not been allocated and is null.
+ */
+ public void set(long index, T value) throws IndexOutOfBoundsException, NullPointerException;
+
+ /**
+ * Returns the value at an index.
+ *
+ * @param index The index to get the value from.
+ * @return The respective value.
+ * @throws IndexOutOfBoundsException When <code>index</code> is less than 0 or
+ * greater or equal to the length.
+ * @throws NullPointerException When the array has not been allocated and is null.
+ */
+ public T at(long index) throws IndexOutOfBoundsException, NullPointerException;
+
+ /**
+ * Converts the native array to a Java array.
+ *
+ * @return A copy of the native array.
+ * @throws NullPointerException When the array has not been allocated and is null.
+ */
+ public T[] toArray() throws NullPointerException;
+
+ /**
+ * Converts the native array to a Java array without creating a new array ensuring
+ * that an array of <code>T</code>'s are returned. This will generally be faster
+ * than calling <code>toArray()</code>.
+ *
+ * @return A copy of the native array.
+ * @throws NullPointerException
+ */
+ public Object toArrayNoConvert() throws NullPointerException;
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return The length.
+ */
+ public long length();
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/NativePointer.java b/demos/java/gsjava/src/com/artifex/gsjava/util/NativePointer.java
new file mode 100644
index 00000000..222ade80
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/NativePointer.java
@@ -0,0 +1,157 @@
+package com.artifex.gsjava.util;
+
+/**
+ * <p>The NativePointer class allows for direct non-managed memory
+ * allocations. The purpose of this class is to provide direct access
+ * to memory blocks.</p>
+ *
+ * <p>An instance of the class is safe in the sense that
+ * no memory can be accessed that is filled with junk which has been
+ * freed, and a check is performed so that in the worst case scenario,
+ * only a Java exception will be thrown. However, an instance of the
+ * class can cause memory leaks if not used correctly as garbage collecting
+ * the object will not free the memory natively, so it will need to be
+ * maintained.</p>
+ *
+ * <p>This class also contains several native methods which can be used
+ * for slightly faster native access to unmanaged memory. These methods
+ * are considered unsafe, and for read/write access to the memory,
+ * an implementation <code>NativeArray</code> should be used.</code>.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class NativePointer {
+
+ static {
+ registerLibraries();
+ }
+
+ /**
+ * Registers the needed native libraries.
+ */
+ private static void registerLibraries() {
+ System.loadLibrary("gs_jni");
+ }
+
+ public static final long NULL = 0x0L;
+
+ public static final long BYTE_SIZE = 1L,
+ CHAR_SIZE = 2L,
+ SHORT_SIZE = 2L,
+ INT_SIZE = 4L,
+ LONG_SIZE = 8L;
+
+ private long address;
+
+ /**
+ * Constructs a null native pointer.
+ */
+ public NativePointer() {
+ address = NULL;
+ }
+
+ /**
+ * Allocates a memory block of size <code>size</code>.
+ *
+ * @param size The size of the block, in bytes.
+ * @throws IllegalStateException When this pointer already points to something.
+ * @throws AllocationError When the native allocation fails.
+ */
+ public final void malloc(long size) throws IllegalStateException, AllocationError {
+ if (address != NULL) {
+ throw new IllegalStateException("Memory already allocated.");
+ }
+ this.address = mallocNative(size);
+ }
+
+ /**
+ * Allocates an block of size <code>count</code> * <code>size</code> with each
+ * byte initialized to 0.
+ *
+ * @param count The number of elements to allocated.
+ * @param size The size of each element, in bytes.
+ * @throws IllegalStateException When this pointer already points to something.
+ * @throws AllocationError When the native allocation fails.
+ */
+ public final void calloc(long count, long size) throws IllegalStateException, AllocationError {
+ if (address != NULL) {
+ throw new IllegalStateException("Memory already allocated.");
+ }
+ this.address = callocNative(count, size);
+ }
+
+ /**
+ * Frees the allocated block, if any has been allocated.
+ */
+ public final void free() {
+ freeNative(address);
+ address = NULL;
+ }
+
+ /**
+ * Returns the native address of this pointer.
+ *
+ * @return The native address.
+ */
+ public final long getAddress() {
+ return address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (o instanceof NativePointer) {
+ return address == ((NativePointer)o).address;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append("0x").append(Long.toHexString(address)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return (int)address;
+ }
+
+ private static native long mallocNative(long size) throws AllocationError;
+
+ private static native long callocNative(long count, long size) throws AllocationError;
+
+ private static native void freeNative(long block);
+
+
+ public static native byte[] byteArrayNative(long address, long len);
+
+ public static native byte byteAtNative(long address, long index);
+
+ public static native void setByteNative(long address, long index, byte value);
+
+ public static native char[] charArrayNative(long address, long len);
+
+ public static native char charAtNative(long address, long index);
+
+ public static native void setCharNative(long address, long index, char value);
+
+ public static native short[] shortArrayNative(long address, long len);
+
+ public static native short shortAtNative(long address, long index);
+
+ public static native void setShortNative(long address, long index, short value);
+
+ public static native int[] intArrayNative(long address, long len);
+
+ public static native int intAtNative(long address, long index);
+
+ public static native void setIntNative(long address, long index, int value);
+
+ public static native long[] longArrayNative(long address, long len);
+
+ public static native long longAtNative(long address, long index);
+
+ public static native void setLongNative(long address, long index, long value);
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java b/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java
new file mode 100644
index 00000000..38a34ac1
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java
@@ -0,0 +1,45 @@
+package com.artifex.gsjava.util;
+
+public class Reference<T> {
+
+ private volatile T value;
+
+ public Reference() {
+ this(null);
+ }
+
+ public Reference(T value) {
+ this.value = value;
+ }
+
+ public void setValue(T value) {
+ this.value = value;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (o == this)
+ return true;
+ if (o instanceof Reference) {
+ Reference<?> ref = (Reference<?>)o;
+ return value == null ? ref.value == null : value.equals(ref.value);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return value == null ? 0 : value.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Reference<" + (value == null ? "?" : value.getClass().getName()) + "> -> " + value;
+ }
+}
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/StringUtil.java b/demos/java/gsjava/src/com/artifex/gsjava/util/StringUtil.java
new file mode 100644
index 00000000..0183ad81
--- /dev/null
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/StringUtil.java
@@ -0,0 +1,41 @@
+package com.artifex.gsjava.util;
+
+/**
+ * Contains utility methods to work with Strings.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class StringUtil {
+
+ /**
+ * Converts a Java String to a null-terminated byte array.
+ *
+ * @param str The string to convert.
+ * @return The result byte array.
+ */
+ public static byte[] toNullTerminatedByteArray(final String str) {
+ final byte[] barray = str.getBytes();
+ final byte[] result = new byte[barray.length + 1];
+ System.arraycopy(barray, 0, result, 0, barray.length);
+ return result;
+ }
+
+ /**
+ * Converts an array of Strings to a 2D byte array of null-terminated
+ * strings.
+ *
+ * @param strs The strings to convert.
+ * @return THe result 2D byte array.
+ */
+ public static byte[][] to2DByteArray(final String[] strs){
+ final byte[][] array = new byte[strs.length][];
+ for (int i = 0; i < strs.length; i++) {
+ final String str = strs[i];
+ array[i] = toNullTerminatedByteArray(str);
+ }
+ return array;
+ }
+
+ private StringUtil() { }
+}
diff --git a/demos/java/gstest/.classpath b/demos/java/gstest/.classpath
new file mode 100644
index 00000000..6d2a9e96
--- /dev/null
+++ b/demos/java/gstest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/gsjava"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/java/gstest/.project b/demos/java/gstest/.project
new file mode 100644
index 00000000..b40f0f4f
--- /dev/null
+++ b/demos/java/gstest/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>gstest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/demos/java/gstest/src/gstest/Main.java b/demos/java/gstest/src/gstest/Main.java
new file mode 100644
index 00000000..ad5b0fb1
--- /dev/null
+++ b/demos/java/gstest/src/gstest/Main.java
@@ -0,0 +1,41 @@
+package gstest;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+import com.artifex.gsjava.GSInstance;
+import com.artifex.gsjava.util.NativePointer;
+import com.artifex.gsjava.util.Reference;
+
+
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+
+ GSInstance instance = new GSInstance();
+ instance.set_arg_encoding(1);
+
+ String[] gsargs = new String[] {
+ "gs",
+ "-sDEVICE=pngalpha",
+ "-r100"
+ };
+
+ instance.init_with_args(gsargs);
+
+ Reference<?> aaRef = new Reference<>();
+ instance.get_param_once("TextAlphaBits", aaRef, GS_SPT_INT);
+ System.out.println("TextAlphaBits=" + aaRef.getValue());
+
+ instance.set_param("TextAlphaBits", 1, GS_SPT_INT);
+
+ NativePointer value = new NativePointer();
+ int bytes = instance.get_param("TextAlphaBits", NativePointer.NULL, GS_SPT_INT);
+ value.malloc(bytes);
+ instance.get_param("TextAlphaBits", value.getAddress(), GS_SPT_INT);
+ int val = NativePointer.intAtNative(value.getAddress(), 0);
+ System.out.println(val);
+ value.free();
+
+ instance.delete_instance();
+ }
+}
diff --git a/demos/java/gsviewer/.classpath b/demos/java/gsviewer/.classpath
new file mode 100644
index 00000000..3ad142b6
--- /dev/null
+++ b/demos/java/gsviewer/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="lib" path="gsjava.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/demos/java/gsviewer/.project b/demos/java/gsviewer/.project
new file mode 100644
index 00000000..5b8f7395
--- /dev/null
+++ b/demos/java/gsviewer/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>gsviewer</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/demos/java/gsviewer/README.txt b/demos/java/gsviewer/README.txt
new file mode 100644
index 00000000..885edf1f
--- /dev/null
+++ b/demos/java/gsviewer/README.txt
@@ -0,0 +1,4 @@
+required libraries in this directory:
+gpdldll64.dll
+gs_jni.dll
+gsjava.jar \ No newline at end of file
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/DefaultUnhandledExceptionHandler.java b/demos/java/gsviewer/src/com/artifex/gsviewer/DefaultUnhandledExceptionHandler.java
new file mode 100644
index 00000000..2074b05b
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/DefaultUnhandledExceptionHandler.java
@@ -0,0 +1,107 @@
+package com.artifex.gsviewer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * The default unhandled exception handler. This will handle exceptions which
+ * are not caught in a try/catch block and print an error message to
+ * <code>System.err</code> and a log file.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class DefaultUnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+ /**
+ * An instance of the exception handler.
+ */
+ public static final DefaultUnhandledExceptionHandler INSTANCE;
+
+ static {
+ INSTANCE = new DefaultUnhandledExceptionHandler();
+ Thread.setDefaultUncaughtExceptionHandler(INSTANCE);
+ }
+
+ private DefaultUnhandledExceptionHandler() { }
+
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ StringBuilder builder = new StringBuilder();
+
+ DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
+ builder.append("Unhandled exception!\n");
+
+ // Print the time of the error
+ builder.append("Time: " + dtf.format(LocalDateTime.now()) + "\n\n");
+
+ // Print all system properties
+ builder.append("PROPERTIES\n");
+ Properties props = System.getProperties();
+ for (Enumeration<Object> keys = props.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement().toString();
+ String prop = props.getProperty(key);
+ String friendly = "\"";
+ for (int i = 0; i < prop.length(); i++) {
+ char c = prop.charAt(i);
+ switch (c) {
+ case '\n':
+ friendly += "\\n";
+ break;
+ case '\r':
+ friendly += "\\r";
+ break;
+ default:
+ friendly += c;
+ break;
+ }
+ }
+ friendly += "\"";
+ builder.append(key + " = " + friendly + "\n");
+ }
+ builder.append('\n');
+
+ // Print the stack trace of the error
+ builder.append("EXCEPTION\n");
+ builder.append("Exception: " + e.getClass().getName() + "\n");
+ builder.append("Message: " + e.getMessage() + "\n");
+ builder.append("Cause: " + (e.getCause() == null ? "[Unknown]" :
+ e.getCause().getClass().getName()) + "\n");
+ builder.append("Thread: " + t.getName() + " (id=" + t.getId() + ")\n");
+ builder.append("Stack trace:" + "\n");
+ builder.append(stackTraceToString(e));
+
+ // Write to System.err and a log file
+ String fullMessage = builder.toString();
+ System.err.println(fullMessage);
+ try {
+ PrintStream out = new PrintStream(new FileOutputStream("error.log"));
+ out.println(fullMessage);
+ out.close();
+ } catch (FileNotFoundException e1) {
+ System.err.println("Failed to write to log file");
+ }
+
+ // Close the program
+ System.exit(1);
+ }
+
+ /**
+ * Converts a stack trace to a string.
+ *
+ * @param e The <code>Throwable</code> whose stack trace should be converted.
+ * @return The stack trace as a string.
+ */
+ private String stackTraceToString(Throwable e) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ PrintStream out = new PrintStream(os);
+ e.printStackTrace(out);
+ return new String(os.toByteArray());
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java
new file mode 100644
index 00000000..6000d3e4
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java
@@ -0,0 +1,1075 @@
+package com.artifex.gsviewer;
+
+import static com.artifex.gsjava.GSAPI.*;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Objects;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.artifex.gsjava.GSInstance;
+import com.artifex.gsjava.callbacks.DisplayCallback;
+import com.artifex.gsjava.util.BytePointer;
+import com.artifex.gsjava.util.Reference;
+import com.artifex.gsviewer.ImageUtil.ImageParams;
+
+import sun.misc.Unsafe;
+
+/**
+ * <p>A Document stores an ordered list of Pages. This class implements
+ * <code>java.util.List</code>, so it inherits all of a list's capabilities,
+ * such as the ability to iterate over the document.</p>
+ *
+ * <p>The Document class also handles loading of pages through Ghostcript
+ * and ensuring that two Ghostscript operations are not running at the
+ * same time.</p>
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class Document implements List<Page> {
+
+ private static final DocumentLoader documentLoader = new DocumentLoader(); // The document loader
+ private static final int format = GS_COLORS_RGB | GS_DISPLAY_DEPTH_8 | GS_DISPLAY_BIGENDIAN; // Format
+
+ private static final ReentrantLock operationLock = new ReentrantLock(); // The operation lock
+ private static final Condition operationCv = operationLock.newCondition(); // The operation condition variable
+ private static volatile boolean operationInProgress = false; // Whether an operation is in progress
+
+ private static GSInstance gsInstance = null;
+
+ /**
+ * Asynchronous execution dispatch returns.
+ */
+ public static final int ASYNC_DISPATCH_OK = 0, ASYNC_DISPATCH_OPERATION_IN_PROGRESS = 1;
+
+ /**
+ * Operation mode indicating the method should wait until a running operation has finished.
+ */
+ public static final int OPERATION_WAIT = 0;
+
+ /**
+ * Operation mode indicating the method should immediately return if an operation is already
+ * running.
+ */
+ public static final int OPERATION_RETURN = 1;
+
+ /**
+ * Operation mode indicating the method should throw an <code>OperationInProgressException</code>
+ * if an operation is already running.
+ */
+ public static final int OPERATION_THROW = 2;
+
+ /**
+ * Loads a document on a separate thread.
+ *
+ * @param file The file to load.
+ * @param cb The callback when loading the document has finished.
+ * @param dlb The callback signifying when progress has occurred while loading.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code>, or
+ * <code>OPERATION_THROW</code> meaning the loader should throw an
+ * <code>OperationInProgressException</code>.
+ *
+ * @return The state of the thread dispatching. This is either <code>ASYNC_DISPATCH_OK</code>
+ * or <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code> which is also dependent on
+ * <code>operationMode</code>.
+ *
+ * @throws NullPointerException When <code>cb</code> is <code>null</code>.
+ * @throws RuntimeException When the current thread fails to wait until a thread has finished
+ * completing an operation.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERTAION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ * @throws OperationInProgressException When an operation is in progress and
+ * <code>operationMode</codeE> is <code>OPERATION_THROW</code>.
+ */
+ public static int loadDocumentAsync(final File file, final DocAsyncLoadCallback cb,
+ final DocLoadProgressCallback dlb, final int operationMode)
+ throws NullPointerException, RuntimeException, IllegalArgumentException,
+ OperationInProgressException {
+ if (!handleOperationMode(operationMode))
+ return ASYNC_DISPATCH_OPERATION_IN_PROGRESS;
+
+ Objects.requireNonNull(cb, "DocAsyncLoadCallback");
+ final Thread t = new Thread(() -> {
+ Document doc = null;
+ Exception exception = null;
+ try {
+ doc = new Document(file, dlb, operationMode);
+ } catch (FileNotFoundException | IllegalStateException | NullPointerException e) {
+ exception = e;
+ }
+ cb.onDocumentLoad(doc, exception);
+ });
+ t.setName("Document-Loader-Thread");
+ t.setDaemon(true);
+ t.start();
+ return ASYNC_DISPATCH_OK;
+ }
+
+ /**
+ * Loads a document on a separate thread.
+ *
+ * @param file The file to load.
+ * @param cb The callback when loading the document has finished.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code>, or
+ * <code>OPERATION_THROW</code> meaning the loader should throw an
+ * <code>OperationInProgressException</code>.
+ *
+ * @return The state of the thread dispatching. This is either <code>ASYNC_DISPATCH_OK</code>
+ * or <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code> which is also dependent on
+ * <code>operationMode</code>.
+ *
+ * @throws NullPointerException When <code>cb</code> is <code>null</code>.
+ * @throws RuntimeException When the current thread fails to wait until a thread has finished
+ * completing an operation.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>ASYNC_OPERTAION_WAIT</coded> or <code>ASYNC_OPERATION_RETURN</code>.
+ */
+ public static int loadDocumentAsync(final File file, final DocAsyncLoadCallback cb,
+ final int operationMode)
+ throws NullPointerException, RuntimeException, IllegalArgumentException {
+ return loadDocumentAsync(file, cb, null, operationMode);
+ }
+
+ /**
+ * Loads a document on a separate thread.
+ *
+ * @param filename The name of the file to load.
+ * @param cb The callback when loading the document has finished.
+ * @param dlb The callback signifying when progress has occurred while loading.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code>, or
+ * <code>OPERATION_THROW</code> meaning the loader should throw an
+ * <code>OperationInProgressException</code>.
+ *
+ * @return The state of the thread dispatching. This is either <code>ASYNC_DISPATCH_OK</code>
+ * or <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code> which is also dependent on
+ * <code>operationMode</code>.
+ *
+ * @throws NullPointerException When <code>cb</code> is <code>null</code>.
+ * @throws RuntimeException When the current thread fails to wait until a thread has finished
+ * completing an operation.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>ASYNC_OPERTAION_WAIT</coded> or <code>ASYNC_OPERATION_RETURN</code>.
+ */
+ public static int loadDocumentAsync(final String filename, final DocAsyncLoadCallback cb,
+ final DocLoadProgressCallback dlb, final int operationMode)
+ throws NullPointerException, RuntimeException, IllegalArgumentException {
+ return loadDocumentAsync(new File(filename), cb, dlb, operationMode);
+ }
+
+ /**
+ * Loads a document on a separate thread.
+ *
+ * @param filename The name of the file to load.
+ * @param cb The callback when loading the document has finished.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code>, or
+ * <code>OPERATION_THROW</code> meaning the loader should throw an
+ * <code>OperationInProgressException</code>.
+ *
+ * @return The state of the thread dispatching. This is either <code>ASYNC_DISPATCH_OK</code>
+ * or <code>ASYNC_DISPATCH_OPERATION_IN_PROGRESS</code> which is also dependent on
+ * <code>operationMode</code>.
+ *
+ * @throws NullPointerException When <code>cb</code> is <code>null</code>.
+ * @throws RuntimeException When the current thread fails to wait until a thread has finished
+ * completing an operation.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>ASYNC_OPERTAION_WAIT</coded> or <code>ASYNC_OPERATION_RETURN</code>.
+ */
+ public static int loadDocumentAsync(final String filename, final DocAsyncLoadCallback cb,
+ final int operationMode)
+ throws NullPointerException, RuntimeException, IllegalArgumentException {
+ return loadDocumentAsync(filename, cb, null, operationMode);
+ }
+
+ /**
+ * Returns whether a file should being distilled to a PDF before loading. Also tests
+ * to make sure that the supplied file is a file type that can be loaded into the viewer.
+ * If the file cannot be loaded into the viewer, an <code>IllegalArgumentException</code>
+ * is thrown.
+ *
+ * @param file The file to test.
+ * @return <code>true</code> if the file should be distilled or <code>false</code>
+ * if it should not.
+ * @throws FileNotFoundException If <code>file</code> does not exist.
+ * @throws IllegalArgumentException If <code>file</code> is not a document which can
+ * be loaded into the viewer.
+ * @throws NullPointerException If <code>file</code> is <code>null</code>.
+ */
+ public static boolean shouldDistill(File file)
+ throws FileNotFoundException, IllegalArgumentException, NullPointerException {
+ if (!Objects.requireNonNull(file, "file is null").exists())
+ throw new FileNotFoundException("File does not exist.");
+ String path = file.getAbsolutePath();
+ int extensionInd = path.lastIndexOf('.');
+ if (extensionInd == -1 || !GSFileFilter.INSTANCE.accept(file))
+ throw new IllegalArgumentException("Invalid file type");
+ String extension = path.substring(extensionInd);
+ return !extension.equalsIgnoreCase(".pdf");
+ }
+
+ /**
+ * Distills a document into a PDF.
+ *
+ * @param input The input file to distill.
+ * @param out The output file to write to. If the file does not exist, it will be
+ * created. If this is <code>null</code>, a temporary file will be created.
+ * @return The file which was written to.
+ * @throws IOException When a file fails to be created.
+ * @throws FileNotFoundException When <code>input</code> does not exist.
+ * @throws IllegalStateException When the file fails to be distilled.
+ */
+ public static File distillDocument(File input, File out) throws IOException, FileNotFoundException, IllegalStateException {
+ if (gsInstance != null)
+ throw new IllegalStateException("gsInstance is non-null");
+
+ if (!input.exists())
+ throw new FileNotFoundException(input.getAbsolutePath());
+
+ out = out == null ? File.createTempFile(input.getName() + ".pdf", null) : out;
+ if (!out.exists())
+ out.createNewFile();
+
+ try {
+ int code = initGSInstance(
+ "gs",
+ "-sDEVICE=pdfwrite",
+ "-dFirstPage=1",
+ "-dDisplayFormat=" + format,
+ "-o", out.getAbsolutePath(),
+ "-f", input.getAbsolutePath()
+ );
+
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to distill document (code = " + code + ")");
+ } finally {
+ deleteGSInstance();
+ }
+ return out;
+ }
+
+ /**
+ * Call, internally, on the start of an operation.
+ */
+ private static void startOperation() {
+ operationInProgress = true;
+ }
+
+ /**
+ * Call, internally, on the start of an operation, before <code>startOperation()</code>.
+ *
+ * @param operationMode The operation mode.
+ * @return Whether the calling function should continue to its operation.
+ * @throws OperationInProgressException When an operation is in progress and <code>operationMode</code>
+ * is <code>OPERATION_THROW</code>. This should not be caught by the calling function, who should
+ * throw it instead.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not a valid operation mode.
+ */
+ private static boolean handleOperationMode(final int operationMode)
+ throws OperationInProgressException, IllegalArgumentException {
+ if (operationInProgress && operationMode == OPERATION_RETURN)
+ return false;
+ else if (operationInProgress && operationMode == OPERATION_THROW) {
+ StackTraceElement[] elems = new Exception().getStackTrace();
+ throw new OperationInProgressException(elems[1].getClassName() + "." + elems[1].getMethodName());
+ } else if (operationInProgress && operationMode == OPERATION_WAIT)
+ waitForOperation();
+ else if (operationInProgress)
+ throw new IllegalArgumentException("Unknown operation mode: " + operationMode);
+ return true;
+ }
+
+ /**
+ * Called internally by <code>handleOperationMode()</code>. Waits for an operation
+ * to finish.
+ */
+ private static void waitForOperation() {
+ operationLock.lock();
+ try {
+ operationCv.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Thread interrupted", e);
+ } finally {
+ operationLock.unlock();
+ }
+ }
+
+ /**
+ * Call, internally, when an operation is done.
+ */
+ private static void operationDone() {
+ operationLock.lock();
+ operationInProgress = false;
+ try {
+ operationCv.signal();
+ } finally {
+ operationLock.unlock();
+ }
+ }
+
+ @FunctionalInterface
+ public static interface DocAsyncLoadCallback {
+
+ /**
+ * Called when a document has finished loading on a separate
+ * thread.
+ *
+ * @param doc The document which was loaded. <code>null</code> if the document
+ * failed to load.
+ * @param exception An exception that ocurred while loading, <code>null</code>
+ * if no exception was thrown.
+ */
+ public void onDocumentLoad(Document doc, Exception exception);
+ }
+
+ @FunctionalInterface
+ public static interface DocLoadProgressCallback {
+
+ /**
+ * Called when the document has made progress while loading.
+ *
+ * @param progress The amount of progress (from 0 to 100).
+ */
+ public void onDocumentProgress(int progress);
+ }
+
+ /**
+ * Exception indicating an operation is already in progress.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+ public static final class OperationInProgressException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public OperationInProgressException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Initializes a new instance of ghostscript.
+ *
+ * @param args The arguments for init_with_args.
+ * @return The return code of init_with_args.
+ * @throws IllegalStateException When any return code of a Ghostscript call is
+ * not <code>GS_ERROR_OK</code>.
+ */
+ private static int initGSInstance(String... args) throws IllegalStateException {
+ deleteGSInstance();
+
+ GSInstance instance = new GSInstance();
+
+ int code;
+ code = instance.set_arg_encoding(1);
+ if (code != GS_ERROR_OK) {
+ instance.delete_instance();
+ throw new IllegalStateException("Failed to set arg encoding (code = " + code + ")");
+ }
+
+ code = instance.set_display_callback(documentLoader.reset());
+ if (code != GS_ERROR_OK) {
+ instance.delete_instance();
+ throw new IllegalStateException("Failed to set display callback (code = " + code + ")");
+ }
+
+ code = instance.init_with_args(args);
+ if (code != GS_ERROR_OK) {
+ instance.delete_instance();
+ throw new IllegalStateException("Failed to init with args (code = " + code + ")");
+ }
+
+ gsInstance = instance;
+ return code;
+ }
+
+ /**
+ * Deletes the current instance of Ghostscript.
+ */
+ private static void deleteGSInstance() {
+ if (gsInstance != null) {
+ gsInstance.exit();
+ gsInstance.delete_instance();
+ gsInstance = null;
+ }
+ }
+
+ /**
+ * Sets Ghostscript parameters.
+ *
+ * @param dpi The dpi to set.
+ * @param startPage The start page to set.
+ * @param lastPage The last page to set.
+ * @throws NullPointerException When the Ghostscript instance is <code>null</code>.
+ * @throws IllegalStateException When any Ghostscript call does not return <code>GS_ERROR_OK</code>.
+ */
+ private static void setParams(int dpi, int startPage, int lastPage) throws NullPointerException, IllegalStateException {
+ if (gsInstance == null)
+ throw new NullPointerException("gsInstance is null");
+
+ int code = gsInstance.set_param("HWResolution", Page.toDPIString(dpi), GS_SPT_PARSED);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set HWResolution (code = " + code + ")");
+ }
+
+ code = gsInstance.set_param("FirstPage", startPage, GS_SPT_INT);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set dFirstPage (code = " + code + ")");
+ }
+
+ code = gsInstance.set_param("LastPage", lastPage, GS_SPT_INT);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set dEndPage (code = " + code + ")");
+ }
+ }
+
+ /**
+ * Class which handles loading a Document.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+ private static class DocumentLoader extends DisplayCallback {
+ private int pageWidth, pageHeight, pageRaster;
+ private BytePointer pimage;
+ private List<BufferedImage> images;
+ private int progress;
+ private DocLoadProgressCallback callback;
+
+ DocumentLoader() {
+ reset();
+ }
+
+ /**
+ * Resets the DcumentLoader to its default values.
+ *
+ * @return <code>this</code>.
+ */
+ DocumentLoader reset() {
+ this.pageWidth = 0;
+ this.pageHeight = 0;
+ this.pageRaster = 0;
+ this.pimage = null;
+ this.images = new LinkedList<>();
+ this.progress = 0;
+ this.callback = null;
+ return this;
+ }
+
+ @Override
+ public int onDisplayPresize(long handle, long device, int width, int height, int raster, int format) {
+ return 0;
+ }
+
+ @Override
+ public int onDisplaySize(long handle, long device, int width, int height, int raster, int format,
+ BytePointer pimage) {
+ this.pageWidth = width;
+ this.pageHeight = height;
+ this.pageRaster = raster;
+ this.pimage = pimage;
+ return 0;
+ }
+
+ @Override
+ public int onDisplayPage(long handle, long device, int copies, boolean flush) {
+ byte[] data = (byte[]) pimage.toArrayNoConvert();
+ images.add(ImageUtil.createImage(data, new ImageParams(pageWidth, pageHeight, pageRaster, BufferedImage.TYPE_3BYTE_BGR)));
+
+ progress += (100 - progress) / 2;
+ if (callback != null)
+ callback.onDocumentProgress(progress);
+
+ return 0;
+ }
+
+ @Override
+ public void finalize() {
+ System.err.println("WARNING: The document loader has been freed by the Java VM");
+ }
+ }
+
+ private File file;
+ private List<Page> pages;
+
+ /**
+ * Creates and loads a new document.
+ *
+ * @param file The file to load.
+ * @param loadCallback The callback to indicate when progress has occurred while loading.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ *
+ * @throws FileNotFoundException When <code>file</code> does not exist.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws NullPointerException When <code>file</code> is <code>null</code>.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public Document(final File file, final DocLoadProgressCallback loadCallback, int operationMode)
+ throws FileNotFoundException, IllegalStateException, NullPointerException,
+ OperationInProgressException, IllegalArgumentException {
+ this.file = Objects.requireNonNull(file, "file");
+ if (!file.exists())
+ throw new FileNotFoundException(file.getAbsolutePath());
+
+ if (!handleOperationMode(operationMode))
+ return;
+
+ try {
+
+ startOperation();
+
+ int code = initGSInstance(
+ "gs",
+ "-sDEVICE=display",
+ "-dFirstPage=1",
+ "-dDisplayFormat=" + format
+ );
+
+ if (gsInstance == null)
+ throw new IllegalStateException("Failed to initialize Ghostscript");
+
+ documentLoader.callback = loadCallback;
+
+
+ code = gsInstance.set_param("HWResolution", Page.toDPIString(Page.PAGE_LOW_DPI), GS_SPT_PARSED);
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to set HWResolution (code = " + code + ")");
+
+ Reference<Integer> exitCode = new Reference<>();
+ code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+
+ boolean aa = Settings.SETTINGS.getSetting("antialiasing");
+ if (aa) {
+ gsInstance.set_param("TextAlphaBits", 4, GS_SPT_INT);
+ gsInstance.set_param("GraphicsAlphaBits", 4, GS_SPT_INT);
+ } else {
+ gsInstance.set_param("TextAlphaBits", 0, GS_SPT_INT);
+ gsInstance.set_param("GraphicsAlphaBits", 0, GS_SPT_INT);
+ }
+
+ this.pages = new ArrayList<>(documentLoader.images.size());
+ for (BufferedImage img : documentLoader.images) {
+ pages.add(new Page(img));
+ }
+
+ if (documentLoader.callback != null)
+ documentLoader.callback.onDocumentProgress(100);
+ } finally {
+ operationDone();
+ }
+ }
+
+ /**
+ * Creates and loads a document from a filename.
+ *
+ * @param file The file to load.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ *
+ * @throws FileNotFoundException When <code>file</code> does not exist.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws NullPointerException When <code>file</code> is <code>null</code>.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public Document(final File file, final int operationMode)
+ throws FileNotFoundException, IllegalStateException, NullPointerException,
+ OperationInProgressException {
+ this(file, null, operationMode);
+ }
+
+ /**
+ * Creates and loads a document from a filename.
+ *
+ * @param filename The name of the file to load.
+ * @param loadCallback The callback to indicate when progress has occurred while loading.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ *
+ * @throws FileNotFoundException When <code>file</code> does not exist.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws NullPointerException When <code>file</code> is <code>null</code>.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public Document(final String filename, final DocLoadProgressCallback loadCallback,
+ final int operationMode)
+ throws FileNotFoundException, IllegalStateException, NullPointerException,
+ OperationInProgressException {
+ this(new File(Objects.requireNonNull(filename, "filename")), loadCallback, operationMode);
+ }
+
+ /**
+ * Creates and loads a document from a filename.
+ *
+ * @param filename The name of the file to load.
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ *
+ * @throws FileNotFoundException When <code>filename</code> does not exist.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws NullPointerException When <code>filename</code> is <code>null</code>.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public Document(final String filename, final int operationMode)
+ throws FileNotFoundException, IllegalStateException, NullPointerException,
+ OperationInProgressException {
+ this(filename, null, operationMode);
+ }
+
+ /**
+ * Loads the high resolution images in a range of images.
+ *
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ * @param startPage The first page to load.
+ * @param endPage The end page to load.
+ *
+ * @throws IndexOutOfBoundsException When <code>firstPage</code> or <code>endPage</code>
+ * are not in the document or <code>endPage</code> is less than <code>firstPage</code>.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ */
+ public void loadHighRes(int operationMode, int startPage, int endPage)
+ throws IndexOutOfBoundsException, IllegalStateException {
+ checkBounds(startPage, endPage);
+
+ if (!handleOperationMode(operationMode))
+ return;
+
+ try {
+ startOperation();
+
+ documentLoader.images.clear();
+
+ setParams(Page.PAGE_HIGH_DPI, startPage, endPage);
+
+ Reference<Integer> exitCode = new Reference<>();
+ int code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+
+ if (documentLoader.images.size() != endPage - startPage + 1) {
+ throw new IllegalStateException("Page range mismatch (expected " +
+ (endPage - startPage) + ", got " + documentLoader.images.size() + ")");
+ }
+
+ int ind = startPage - 1;
+ for (final BufferedImage img : documentLoader.images) {
+ this.pages.get(ind++).setHighRes(img);
+ }
+ } finally {
+ operationDone();
+ }
+ }
+
+ /**
+ * Loads the high resolution image of a singular page.
+ *
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ * @param page The page to load.
+ *
+ * @throws IndexOutOfBoundsException When <code>page</code> is not in the document.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public void loadHighRes(int operationMode, int page)
+ throws IndexOutOfBoundsException, IllegalStateException, OperationInProgressException {
+ loadHighRes(operationMode, page, page);
+ }
+
+ /**
+ * Unloads the high resolution images in a range of pages.
+ *
+ * @param startPage The start page to unload the high resolution image from.
+ * @param endPage The end page to unload the high resolution image from.
+ *
+ * @throws IndexOutOfBoundsException When <code>startPage</code> and <code>endPage</code>
+ * are outside document or <code>endPage</code> is less than <code>startPage</code>.
+ */
+ public void unloadHighRes(int startPage, int endPage) throws IndexOutOfBoundsException {
+ checkBounds(startPage, endPage);
+ for (int i = startPage - 1; i < endPage; i++) {
+ pages.get(i).unloadHighRes();
+ }
+ }
+
+ /**
+ * Unloads a high resolution image at the given page.
+ *
+ * @param page The page to unload the high resolution image.
+ *
+ * @throws IndexOutOfBoundsException When page is not a page in the document.
+ */
+ public void unloadHighRes(int page) throws IndexOutOfBoundsException {
+ unloadHighRes(page, page);
+ }
+
+ /**
+ * Unloads the zoomed images for a range of pages.
+ *
+ * @param startPage The start page to unload.
+ * @param endPage The end page to unload.
+ *
+ * @throws IndexOutOfBoundsException When <code>startPage</code> and <code>endPage</code>
+ * are outside document or <code>endPage</code> is less than <code>startPage</code>.
+ */
+ public void unloadZoomed(int startPage, int endPage) throws IndexOutOfBoundsException {
+ checkBounds(startPage, endPage);
+ for (int i = startPage; i < endPage; i++) {
+ pages.get(i).unloadZoomed();
+ }
+ }
+
+ /**
+ * Unloads a zoomed image for a page.
+ *
+ * @param page The page to unload.
+ *
+ * @throws IndexOutOfBoundsException When <code>page</code> is not in the document.
+ */
+ public void unloadZoomed(int page) throws IndexOutOfBoundsException {
+ unloadZoomed(page, page);
+ }
+
+ /**
+ * Unloads the document's resources. The document will be unusable after this
+ * call.
+ */
+ public void unload() {
+ if (pages != null)
+ deleteGSInstance();
+
+ for (Page p : pages) {
+ p.unloadAll();
+ }
+ pages.clear();
+ pages = null;
+ }
+
+ /**
+ * Returns the name of the document loaded.
+ *
+ * @return The name.
+ */
+ public String getName() {
+ return file.getName();
+ }
+
+ /**
+ * Zooms the area around page <code>page</code>. The area around <code>page</code>
+ * is <code>page - 1</code> to <code>page + 1</code>. The method will automatically
+ * handle if <code>page - 1</code> or <code>page + 1</code> are out of range. However,
+ * it does not handle if <code>page</code> is not in the document.
+ *
+ * @param operationMode How the loader should behave if an operation is already in
+ * progress. Can be <code>OPERATION_WAIT</code>, meaning the loader should
+ * wait until a running operation has finished, <code>OPERATION_RETURN</code> meaning
+ * the loader should immediately return, or <code>OPERATION_THROW</code> meaning the loader
+ * should throw an <code>OperationInProgressException</code>.
+ * @param page The page to load around.
+ * @param zoom The zoom of the pages.
+ *
+ * @throws IndexOutOfBoundsException When <code>page</code> is not in the document.
+ * @throws IllegalStateException When Ghostscript fails to initialize or load the document.
+ * @throws OperationInProgressException When an operation is already in progress
+ * and <code>operationMode</code> is <code>OPERATION_THROW</code>.
+ * @throws IllegalArgumentException When <code>operationMode</code> is not
+ * <code>OPERATION_WAIT</coded>, <code>OPERATION_RETURN</code>, or <code>OPERATION_THROW</code>.
+ */
+ public void zoomArea(final int operationMode, final int page, final double zoom)
+ throws IndexOutOfBoundsException {
+ checkBounds(page, page);
+
+ if (!handleOperationMode(operationMode))
+ return;
+
+ try {
+ startOperation();
+
+ int start = page - 1;
+ start = start < 1 ? page : start;
+ int end = page + 1;
+ end = end > pages.size() ? page : end;
+
+ documentLoader.images.clear();
+
+ setParams((int)(Page.PAGE_HIGH_DPI * zoom), start, end);
+
+ Reference<Integer> exitCode = new Reference<>();
+ int code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+
+ int ind = start - 1;
+ for (final BufferedImage img : documentLoader.images) {
+ this.pages.get(ind++).setZoomed(img);
+ }
+ } finally {
+ operationDone();
+ }
+ }
+
+ public void zoomPage(final int operationMode, final int page, final double zoom)
+ throws IndexOutOfBoundsException {
+ checkBounds(page, page);
+
+ if (!handleOperationMode(operationMode))
+ return;
+
+ try {
+ startOperation();
+
+ setParams((int)(Page.PAGE_HIGH_DPI * zoom), page, page);
+
+ Reference<Integer> exitCode = new Reference<>();
+ int code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK)
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+
+ int ind = page - 1;
+ for (final BufferedImage img : documentLoader.images) {
+ this.pages.get(ind++).setZoomed(img);
+ }
+
+ } finally {
+ operationDone();
+ }
+ }
+
+ /**
+ * Checks to make sure the pages <code>start</code> through
+ * <code>end</code> are in the document, and throws an
+ * <code>IndexOutOfBoundsException</code> if they are not.
+ *
+ * @param start The start page.
+ * @param end The end page.
+ * @throws IndexOutOfBoundsException When <code>startPage</code> and <code>endPage</code>
+ * are outside document or <code>endPage</code> is less than <code>startPage</code>.
+ */
+ private void checkBounds(int start, int end) throws IndexOutOfBoundsException {
+ if (start < 1 || start > pages.size())
+ throw new IndexOutOfBoundsException("start=" + start);
+ if (end < 1 || end > pages.size())
+ throw new IndexOutOfBoundsException("end=" + end);
+ if (end < start)
+ throw new IndexOutOfBoundsException("end < start");
+ }
+
+ // Implementations of inherited methods from java.util.List.
+
+ @Override
+ public int size() {
+ return pages.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return pages.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return pages.contains(o);
+ }
+
+ @Override
+ public Iterator<Page> iterator() {
+ return pages.iterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return pages.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return pages.toArray(a);
+ }
+
+ @Override
+ public boolean add(Page e) {
+ return pages.add(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return pages.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return pages.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Page> c) {
+ return pages.addAll(c);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends Page> c) {
+ return pages.addAll(index, c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ return pages.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ return pages.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ pages.clear();
+ }
+
+ @Override
+ public Page get(int index) {
+ return pages.get(index);
+ }
+
+ @Override
+ public Page set(int index, Page element) {
+ return pages.set(index, element);
+ }
+
+ @Override
+ public void add(int index, Page element) {
+ pages.add(index, element);
+ }
+
+ @Override
+ public Page remove(int index) {
+ return pages.remove(index);
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return pages.indexOf(o);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return pages.lastIndexOf(o);
+ }
+
+ @Override
+ public ListIterator<Page> listIterator() {
+ return pages.listIterator();
+ }
+
+ @Override
+ public ListIterator<Page> listIterator(int index) {
+ return pages.listIterator(index);
+ }
+
+ @Override
+ public Document subList(int fromIndex, int toIndex) {
+ try {
+ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ Unsafe unsafe = (Unsafe)unsafeField.get(null);
+ Document doc = (Document)unsafe.allocateInstance(Document.class);
+ doc.pages = pages.subList(fromIndex, toIndex);
+ doc.file = file;
+ return doc;
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException
+ | IllegalAccessException | InstantiationException e) {
+ throw new RuntimeException("Failed to create sublist: " + e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Document[numPages=" + size() + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (o instanceof Document) {
+ return pages.equals(((Document)o).pages);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return pages.hashCode();
+ }
+
+ @Override
+ protected void finalize() {
+ unload();
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/GSFileFilter.java b/demos/java/gsviewer/src/com/artifex/gsviewer/GSFileFilter.java
new file mode 100644
index 00000000..85033c5a
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/GSFileFilter.java
@@ -0,0 +1,50 @@
+package com.artifex.gsviewer;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * <p>A file filter used for the file choose to only accept certain
+ * file extensions.</p>
+ *
+ * <p>This file filter only accepts files of type ".pdf", ".eps", ".ps",
+ * ".xps", ".oxps", and ".bin"</p>
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class GSFileFilter extends FileFilter {
+
+ /**
+ * An instance of the file filter.
+ */
+ public static final GSFileFilter INSTANCE = new GSFileFilter();
+
+ @Override
+ public boolean accept(File f) {
+ if (f.isDirectory())
+ return true;
+ final String name = f.getName();
+ final int ind = name.lastIndexOf('.');
+ if (ind < 0)
+ return false;
+ final String ext = name.substring(ind);
+ return
+ equals(ext, ".pdf") ||
+ equals(ext, ".eps") ||
+ equals(ext, ".ps") ||
+ equals(ext, ".xps") ||
+ equals(ext, ".oxps") ||
+ equals(ext, ".bin");
+ }
+
+ @Override
+ public String getDescription() {
+ return "Ghostscript Files";
+ }
+
+ private boolean equals(String extension, String compare) {
+ return extension.equalsIgnoreCase(compare);
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/ImageUtil.java b/demos/java/gsviewer/src/com/artifex/gsviewer/ImageUtil.java
new file mode 100644
index 00000000..3754d6f7
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/ImageUtil.java
@@ -0,0 +1,45 @@
+package com.artifex.gsviewer;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+public class ImageUtil {
+
+ public static BufferedImage createImage(final byte[] data, final ImageParams params) {
+ final DataBuffer dataBuffer = new DataBufferByte(data, data.length);
+ final WritableRaster wraster = Raster.createInterleavedRaster(dataBuffer, params.width,
+ params.height, params.raster, 3, new int[] { 0, 1, 2 }, new Point());
+ final ColorModel model = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ new int[] { 8, 8, 8 }, false, false, ColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
+
+ return new BufferedImage(model, wraster, false, null);
+ }
+
+ public static class ImageParams {
+ public int width;
+ public int height;
+ public int raster;
+ public int format;
+
+ public ImageParams() {
+ this(0, 0, 0, 0);
+ }
+
+ public ImageParams(final int width, final int height, final int raster, final int format) {
+ this.width = width;
+ this.height = height;
+ this.raster = raster;
+ this.format = format;
+ }
+ }
+
+ private ImageUtil() { }
+
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Main.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Main.java
new file mode 100644
index 00000000..beecdd3b
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Main.java
@@ -0,0 +1,42 @@
+package com.artifex.gsviewer;
+
+import java.io.IOException;
+
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+import com.artifex.gsviewer.gui.ViewerWindow;
+
+public class Main {
+
+ public static void main(String[] args) {
+ Runtime.getRuntime().addShutdownHook(new Thread(new Shutdown()));
+
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | UnsupportedLookAndFeelException e) {
+ System.err.println("Failed to set Look and Feel: " + e);
+ }
+
+ ViewerWindow win = new ViewerWindow(new ViewerController());
+ SwingUtilities.invokeLater(() -> {
+ win.setVisible(true);
+ });
+ }
+
+ private static class Shutdown implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ Settings.SETTINGS.save();
+ } catch (IOException e) {
+ System.err.println("Failed to write settings file");
+ e.printStackTrace();
+ }
+ }
+
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/PDFFileFilter.java b/demos/java/gsviewer/src/com/artifex/gsviewer/PDFFileFilter.java
new file mode 100644
index 00000000..e7bd7046
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/PDFFileFilter.java
@@ -0,0 +1,28 @@
+package com.artifex.gsviewer;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class PDFFileFilter extends FileFilter {
+
+ public static final PDFFileFilter INSTANCE = new PDFFileFilter();
+
+ @Override
+ public boolean accept(File f) {
+ if (f.isDirectory())
+ return true;
+ String filename = f.getName();
+ int ind = filename.lastIndexOf('.');
+ if (ind == -1)
+ return false;
+ String ext = filename.substring(ind);
+ return ext.equalsIgnoreCase(".pdf");
+ }
+
+ @Override
+ public String getDescription() {
+ return "PDF Files";
+ }
+
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java
new file mode 100644
index 00000000..a3435f56
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java
@@ -0,0 +1,359 @@
+package com.artifex.gsviewer;
+
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.util.Collection;
+import java.util.HashSet;
+
+import com.artifex.gsviewer.ImageUtil.ImageParams;
+
+/**
+ * A Page represents an individual page within a Document. It stores a high resolution image,
+ * a low resolution preview image, and a zoomed image if the viewer is zoomed.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class Page {
+
+ /**
+ * The high-resolution DPI to use.
+ */
+ public static final int PAGE_HIGH_DPI = 72;
+
+ /**
+ * The low-resolution DPI to use.
+ */
+ public static final int PAGE_LOW_DPI = 10;
+
+ /**
+ * Converts a dpi value to a Ghostscript-friendly string.
+ *
+ * @param dpi The dpi to convert.
+ * @return The respective string.
+ */
+ public static String toDPIString(int dpi) {
+ return "[" + dpi + " " + dpi + "]";
+ }
+
+ private volatile BufferedImage lowRes; // The low resolution image
+ private volatile BufferedImage highRes; // The high resolution image
+ private volatile BufferedImage zoomed; // The zoomed image based on the zoom of the viewer
+
+ private Collection<PageUpdateCallback> callbacks; // The page callbacks
+
+ /**
+ * Creates a new page with now low-resolution or high-resolution image.
+ */
+ public Page() {
+ this(null, null);
+ }
+
+ /**
+ * Creates a new page with a low-resolution image.
+ *
+ * @param lowRes The low-resolution image.
+ */
+ public Page(final BufferedImage lowRes) {
+ this(lowRes, null);
+ }
+
+ /**
+ * Creates a new page with a low-resolution image and a high-resolution image.
+ *
+ * @param lowRes The low-resolution image.
+ * @param highRes The high-resolution image.
+ */
+ public Page(final BufferedImage lowRes, final BufferedImage highRes) {
+ this.lowRes = lowRes;
+ this.highRes = highRes;
+ this.callbacks = new HashSet<>();
+ }
+
+ /**
+ * Loads a high resolution image from data.
+ *
+ * @param data The raw image data.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param raster The length of one line of the image in bytes.
+ * @param format The image format.
+ */
+ public void loadHighRes(final byte[] data, final int width, final int height, final int raster, final int format) {
+ setHighRes(ImageUtil.createImage(data, new ImageParams(width, height, raster, format)));
+ }
+
+ /**
+ * Sets the high resolution image
+ *
+ * @param highRes An image.
+ */
+ public void setHighRes(final BufferedImage highRes) {
+ unloadHighRes();
+ this.highRes = highRes;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onLoadHighRes();
+ cb.onPageUpdate();
+ }
+ }
+
+ /**
+ * Unloads the high-resolution image. If none is loaded, this method
+ * does nothing.
+ */
+ public void unloadHighRes() {
+ if (highRes != null) {
+ highRes.flush();
+ highRes = null;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onUnloadHighRes();
+ cb.onPageUpdate();
+ }
+ }
+ }
+
+ /**
+ * Loads a low resolution image from data.
+ *
+ * @param data The raw image data.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param raster The length of one line of the image in bytes.
+ * @param format The image format.
+ */
+ public void loadLowRes(final byte[] data, final int width, final int height, final int raster, final int format) {
+ setLowRes(ImageUtil.createImage(data, new ImageParams(width, height, raster, format)));
+ }
+
+ /**
+ * Sets the low resolution image
+ *
+ * @param lowRes An image.
+ */
+ public void setLowRes(final BufferedImage lowRes) {
+ unloadLowRes();
+ this.lowRes = lowRes;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onLoadLowRes();
+ cb.onPageUpdate();
+ }
+ }
+
+ /**
+ * Unloads the low-resolution image. If none is loaded, this method
+ * does nothing.
+ */
+ public void unloadLowRes() {
+ if (lowRes != null) {
+ lowRes.flush();
+ lowRes = null;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onUnloadLowRes();
+ cb.onPageUpdate();
+ }
+ }
+ }
+
+ /**
+ * Loads a zoomed image from data.
+ *
+ * @param data The raw image data.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param raster The length of one line of the image in bytes.
+ * @param format The image format.
+ */
+ public void loadZoomed(final byte[] data, final int width, final int height,
+ final int raster, final int format) {
+ setZoomed(ImageUtil.createImage(data, new ImageParams(width, height, raster, format)));
+ }
+
+ /**
+ * Sets the zoomed image
+ *
+ * @param zoomed An image.
+ */
+ public void setZoomed(final BufferedImage zoomed) {
+ unloadZoomed();
+ this.zoomed = zoomed;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onLoadZoomed();
+ cb.onPageUpdate();
+ }
+ }
+
+ /**
+ * Unloads the zoomed image. If none is loaded, this method
+ * does nothing.
+ */
+ public void unloadZoomed() {
+ if (zoomed != null) {
+ zoomed.flush();
+ zoomed = null;
+ for (PageUpdateCallback cb : callbacks) {
+ cb.onUnloadZoomed();
+ cb.onPageUpdate();
+ }
+ }
+ }
+
+ /**
+ * Unloads all images. If no images are loaded, this method
+ * does nothing.
+ */
+ public void unloadAll() {
+ unloadLowRes();
+ unloadHighRes();
+ unloadZoomed();
+ }
+
+ /**
+ * Returns the current low-resolution image.
+ *
+ * @return The current low-resolution image, or <code>null</code>
+ * if none is loaded.
+ */
+ public BufferedImage getLowResImage() {
+ return lowRes;
+ }
+
+ /**
+ * Returns the current high-resolution image.
+ *
+ * @return The current high-resolution image, or <code>null</code>
+ * if none is loaded.
+ */
+ public BufferedImage getHighResImage() {
+ return highRes;
+ }
+
+ /**
+ * Returns the current zoomed image.
+ *
+ * @return The current zoomed image, or <code>null</code>
+ * if none is loaded.
+ */
+ public BufferedImage getZoomedImage() {
+ return zoomed;
+ }
+
+ /**
+ * Returns the non-zoomed highest resolution image which can be
+ * displayed.
+ *
+ * @return The highest resolution, non-zoomed image which can be
+ * displayed. If no non-zoomed images are loaded, <code>null</code>
+ * is returned.
+ */
+ public BufferedImage getDisplayableImage() {
+ return highRes == null ? lowRes : highRes;
+ }
+
+ /**
+ * Returns the size of the low-resolution image.
+ *
+ * @return The size of the low-resolution image, or <code>null</code>
+ * if it is not loaded.
+ */
+ public Dimension getLowResSize() {
+ return lowRes == null ? null : new Dimension(lowRes.getWidth(), lowRes.getHeight());
+ }
+
+ /**
+ * Returns the size of the high-resolution image.
+ *
+ * @return The size of the high-resolution image, or <code>null</code>
+ * if it is not loaded.
+ */
+ public Dimension getHighResSize() {
+ return highRes == null ? null : new Dimension(highRes.getWidth(), highRes.getHeight());
+ }
+
+ /**
+ * Returns the size of the zoomed image.
+ *
+ * @return The size of the zoomed image, or <code>null</code>
+ * if it is not loaded.
+ */
+ public Dimension getZoomedSize() {
+ return zoomed == null ? null : new Dimension(zoomed.getWidth(), zoomed.getHeight());
+ }
+
+ /**
+ * Returns the size of the non-zoomed highest resolution image which
+ * can be displayed.
+ *
+ * @return The size of the highest resolution, non-zoomed image which
+ * can be displayed. If no non-zoomed images are loaded, <code>null</code>
+ * is returned.
+ */
+ public Dimension getDisplayableSize() {
+ return highRes == null ? getLowResSize() : getHighResSize();
+ }
+
+ /**
+ * Returns the actual size of the image.
+ *
+ * @return The size of the page, or <code>null</code> if no images are
+ * loaded.
+ */
+ public Dimension getSize() {
+ Dimension size = getHighResSize();
+ if (size != null)
+ return size;
+ size = getLowResSize();
+ if (size == null)
+ return new Dimension(0, 0);
+ return new Dimension(size.width * PAGE_HIGH_DPI / PAGE_LOW_DPI,
+ size.height * PAGE_HIGH_DPI / PAGE_LOW_DPI);
+ }
+
+ /**
+ * Adds a <code>PageUpdateCallback</code> to receive callbacks regarding
+ * page change events.
+ *
+ * @param cb The callback to add.
+ */
+ public void addCallback(PageUpdateCallback cb) {
+ callbacks.add(cb);
+ cb.onPageUpdate();
+ }
+
+ /**
+ * Removes a callback added through <code>addCallback</code>. If the supplied
+ * callback was not added, this method does nothing.
+ *
+ * @param cb The callback to remove.
+ */
+ public void removeCallback(PageUpdateCallback cb) {
+ callbacks.remove(cb);
+ }
+
+ @Override
+ public String toString() {
+ return "Page[lowResLoaded=" + (lowRes != null) + ",highResLoaded=" + (highRes != null) + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (o instanceof Page) {
+ Page p = (Page)o;
+ boolean first = lowRes == null ? p.lowRes == null : lowRes.equals(p.lowRes);
+ boolean second = highRes == null ? p.highRes == null : highRes.equals(p.highRes);
+ return first && second;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (lowRes == null ? 0 : lowRes.hashCode()) + (highRes == null ? 0 : highRes.hashCode());
+ }
+
+ @Override
+ public void finalize() {
+ unloadAll();
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/PageUpdateCallback.java b/demos/java/gsviewer/src/com/artifex/gsviewer/PageUpdateCallback.java
new file mode 100644
index 00000000..6efaf69e
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/PageUpdateCallback.java
@@ -0,0 +1,15 @@
+package com.artifex.gsviewer;
+
+public interface PageUpdateCallback {
+
+ public void onPageUpdate();
+
+ public void onLoadLowRes();
+ public void onUnloadLowRes();
+
+ public void onLoadHighRes();
+ public void onUnloadHighRes();
+
+ public void onLoadZoomed();
+ public void onUnloadZoomed();
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Settings.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Settings.java
new file mode 100644
index 00000000..13f6d6b7
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Settings.java
@@ -0,0 +1,142 @@
+package com.artifex.gsviewer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Settings {
+
+ public static final String SETTINGS_FILE = "gsviewer.cfg";
+
+ public static final Settings SETTINGS;
+
+ static {
+ SETTINGS = new Settings(SETTINGS_FILE);
+ }
+
+ private Map<String, Object> settingsMap;
+ private String filename;
+
+ private Settings(String filename) {
+ this.filename = filename;
+ this.settingsMap = new HashMap<>();
+ loadDefaultSettings();
+
+ File f = new File(filename);
+ if (!f.exists())
+ return;
+
+ try {
+ InputStream in = new FileInputStream(filename);
+ int b;
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+ while ((b = in.read()) != -1) {
+ bout.write(b);
+ }
+
+ in.close();
+ bout.close();
+
+ byte[] array = bout.toByteArray();
+ loadFromString(new String(array));
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to load settings file: " + SETTINGS_FILE, e);
+ }
+ }
+
+ private void loadDefaultSettings() {
+ putSetting("scrollSens", 50);
+ putSetting("preloadRange", 2);
+ putSetting("antialiasing", true);
+ }
+
+ private void loadFromString(String data) {
+ String[] lines = data.split("\n");
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ String[] tokens = line.split(" ");
+ if (tokens.length != 3)
+ throw new IllegalStateException("Malformed settings file (line " + (i + 1) + ")");
+ try {
+ switch (tokens[0]) {
+ case "int":
+ putSetting(tokens[1], Integer.parseInt(tokens[2]));
+ break;
+ case "double":
+ putSetting(tokens[1], Double.parseDouble(tokens[2]));
+ break;
+ case "bool":
+ putSetting(tokens[1], Boolean.parseBoolean(tokens[2]));
+ break;
+ default:
+ throw new IllegalStateException("Invalid type specifier \"" + tokens[0] + "\" (line " + (i + 1) + ")");
+ }
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("Invalid value \"" + tokens[2] + "\" for type " +
+ tokens[0] + " (line " + (i + 1) + ")", e);
+ }
+ }
+ }
+
+ /**
+ * Returns the value of a setting of type name <code>key</code>.
+ *
+ * @param <T> The type of setting stored.
+ * @param key The name of the setting.
+ * @return The respective setting, casted to <code>T</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T getSetting(String key) {
+ return (T)settingsMap.get(key);
+ }
+
+ public void putSetting(String key, Object value) {
+ settingsMap.put(key, value);
+ }
+
+ public void setSetting(String key, Object value) throws IllegalArgumentException {
+ if (settingsMap.get(key) == null) {
+ putSetting(key, value);
+ } else if (settingsMap.get(key).getClass() == value.getClass()) {
+ putSetting(key, value);
+ } else {
+ throw new IllegalArgumentException("value is not type " +
+ settingsMap.get(key).getClass().getName() + " (got " + (value == null ? "null" : value.getClass().getName()) + ")");
+ }
+ }
+
+ public void save() throws IOException {
+ StringBuilder data = new StringBuilder();
+
+ for (String setting : settingsMap.keySet()) {
+ Object value = settingsMap.get(setting);
+ if (value.getClass() == Integer.class) {
+ data.append("int ");
+ } else if (value.getClass() == Double.class) {
+ data.append("double ");
+ } else if (value.getClass() == Boolean.class) {
+ data.append("bool ");
+ }
+ data.append(setting);
+ data.append(' ');
+ data.append(value);
+ data.append('\n');
+ }
+
+ OutputStream out = new FileOutputStream(filename);
+ out.write(data.toString().getBytes());
+ out.close();
+ }
+
+ @Override
+ public String toString() {
+ return settingsMap.toString() + " at " + filename;
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/StdIO.java b/demos/java/gsviewer/src/com/artifex/gsviewer/StdIO.java
new file mode 100644
index 00000000..4ea1b205
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/StdIO.java
@@ -0,0 +1,38 @@
+package com.artifex.gsviewer;
+
+import com.artifex.gsjava.callbacks.IStdErrFunction;
+import com.artifex.gsjava.callbacks.IStdInFunction;
+import com.artifex.gsjava.callbacks.IStdOutFunction;
+
+/**
+ * Implementation of <code>IStdOutFunction</code>, <code>IStdErrFunction</code>, and
+ * <code>IStdInFunction</code> to get IO data from Ghostscript.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class StdIO implements IStdOutFunction, IStdErrFunction, IStdInFunction {
+
+ public static final boolean ENABLE_STD_OUT_IO = false;
+ public static final boolean ENABLE_STD_ERR_IO = true;
+
+ @Override
+ public int onStdIn(long callerHandle, byte[] buf, int len) {
+ return len;
+ }
+
+ @Override
+ public int onStdErr(long callerHandle, byte[] str, int len) {
+ if (ENABLE_STD_ERR_IO)
+ System.err.println(new String(str));
+ return len;
+ }
+
+ @Override
+ public int onStdOut(long callerHandle, byte[] str, int len) {
+ if (ENABLE_STD_OUT_IO)
+ System.out.println(new String(str));
+ return len;
+ }
+
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/ViewerController.java b/demos/java/gsviewer/src/com/artifex/gsviewer/ViewerController.java
new file mode 100644
index 00000000..f2801426
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/ViewerController.java
@@ -0,0 +1,372 @@
+package com.artifex.gsviewer;
+
+import java.awt.HeadlessException;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.swing.JFileChooser;
+import com.artifex.gsviewer.gui.SettingsDialog;
+import com.artifex.gsviewer.gui.ViewerGUIListener;
+import com.artifex.gsviewer.gui.ViewerWindow;
+
+/**
+ * The ViewerController is an implementation of a <code>ViewerGUIListener</code>
+ * used to control the main logic of the viewer such as determining what pages
+ * should be loaded.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class ViewerController implements ViewerGUIListener {
+
+ /**
+ * The lock for the SmartLoader.
+ */
+ private static final Lock lock = new ReentrantLock();
+
+ /**
+ * The condition variable for the SmartLoader to signal when an operation
+ * needs to happen.
+ */
+ private static final Condition cv = lock.newCondition();
+
+ /**
+ * The flag for the smart loader to read after completing an operation. If
+ * this flag is <code>true</code>, the SmartLoader will skip waiting for
+ * <code>cv</code> to be signaled and will immediately continue to the next
+ * operation.
+ */
+ private static volatile boolean outOfDate = true;
+
+ private ViewerWindow source; // The viewer window where documents will be displayed
+ private Document currentDocument; // The current document loaded in the viewer
+ private SmartLoader smartLoader; // The SmartLoader used to load pages based on scroll and zoom
+ private boolean loadingDocument;
+
+ /**
+ * <p>Opens a document from a files asynchronously.</p>
+ *
+ * <p>This method handles distilling files if they should be distilled and the user
+ * chooses to distill them.</p>
+ *
+ * @param file The file to load.
+ * @throws NullPointerException When <code>file</code> is <code>null</code>.
+ * @throws IllegalArgumentException If <code>file</code> is not a file type which can be loaded
+ * into the viewer, if distilling occurs and fails.
+ * @throws FileNotFoundException When <code>file</code> does not exist.
+ * @throws IOException If distilling occurs and a temporary files to be created.
+ * @throws HeadlessException If distilling occurs and <code>GraphicsEnvironment.isHeadless()</code> returns
+ * <code>true</code>.
+ * @throws RuntimeException When an error occurs while launching the loader thread.
+ */
+ public void open(File file)
+ throws NullPointerException, IllegalArgumentException, FileNotFoundException, IOException,
+ HeadlessException, RuntimeException {
+ if (loadingDocument) {
+ source.showWarningDialog("Error", "A document is already loading");
+ return;
+ }
+ if (Document.shouldDistill(file)) {
+ int ret = source.showConfirmDialog("Distill", "Would you like to distill this document before opening?");
+ if (ret == ViewerWindow.CANCEL)
+ return;
+ else if (ret == ViewerWindow.YES) {
+ try {
+ JFileChooser chooser = new JFileChooser();
+ chooser.setCurrentDirectory(new File("."));
+ chooser.setFileFilter(PDFFileFilter.INSTANCE);
+ ret = chooser.showSaveDialog(source);
+ if (ret != JFileChooser.APPROVE_OPTION)
+ return;
+ File out = chooser.getSelectedFile();
+ String filepath = out.getAbsolutePath();
+ if (filepath.lastIndexOf('.') == -1)
+ out = new File(filepath + ".pdf");
+ if (out.exists()) {
+ ret = source.showConfirmDialog("Overwrite?", out.getName() + " already exists. Overwrite?");
+ if (ret != ViewerWindow.YES)
+ return;
+ }
+ if (currentDocument != null)
+ close();
+ file = Document.distillDocument(file, out);
+ } catch (IllegalStateException | IOException e) {
+ System.err.println("Failed to distill: " + e);
+ }
+ }
+ }
+
+ if (currentDocument != null)
+ close();
+ loadingDocument = true;
+ Document.loadDocumentAsync(file, (final Document doc, final Exception exception) -> {
+ try {
+ source.loadDocumentToViewer(doc);
+ source.setLoadProgress(0);
+ if (exception != null) {
+ throw new RuntimeException("Failed to load", exception);
+ //source.showErrorDialog("Failed to load", exception.toString());
+ } else {
+ this.currentDocument = doc;
+ dispatchSmartLoader();
+ }
+ source.revalidate();
+ } finally {
+ loadingDocument = false;
+ }
+ }, (int progress) -> {
+ source.setLoadProgress(progress);
+ }, Document.OPERATION_RETURN);
+ }
+
+ /**
+ * Closes the currently loaded document, if one is loaded. If no document
+ * is loaded, this method does nothing.
+ */
+ public void close() {
+ if (loadingDocument) {
+ source.showWarningDialog("Error", "A document is already loading");
+ return;
+ }
+
+ if (smartLoader != null) {
+ smartLoader.stop();
+ smartLoader = null;
+ }
+
+ if (currentDocument != null) {
+ source.loadDocumentToViewer(null);
+ currentDocument.unload();
+ currentDocument = null;
+ }
+ }
+
+ /**
+ * Returns the current document being viewed.
+ *
+ * @return The current document being viewed or <code>null</code> if
+ * no document is being viewed.
+ */
+ public Document getCurrentDocument() {
+ return currentDocument;
+ }
+
+ @Override
+ public void onViewerAdd(ViewerWindow source) {
+ this.source = source;
+ Thread.setDefaultUncaughtExceptionHandler(new UnhandledExceptionHandler());
+ }
+
+ @Override
+ public void onPageChange(int oldPage, int newPage) {
+ smartLoader.signalOutOfDate();
+ }
+
+ @Override
+ public void onZoomChange(double oldZoom, double newZoom) {
+ if (newZoom > 1.0) {
+ smartLoader.resetZoom();
+ smartLoader.signalOutOfDate();
+ }
+ }
+
+ @Override
+ public void onScrollChange(int newScroll) {
+ if (smartLoader != null)
+ smartLoader.signalOutOfDate();
+ }
+
+ @Override
+ public void onOpenFile() {
+ JFileChooser chooser = new JFileChooser();
+ chooser.setFileFilter(GSFileFilter.INSTANCE);
+ chooser.setCurrentDirectory(new File("").getAbsoluteFile());
+ int status = chooser.showOpenDialog(source);
+ if (status == JFileChooser.APPROVE_OPTION) {
+ try {
+ open(chooser.getSelectedFile());
+ } catch (IOException | RuntimeException e) {
+ source.showErrorDialog("Failed to Open", "Failed to open file (" + e + ")");
+ }
+ }
+ }
+
+ @Override
+ public void onCloseFile() {
+ close();
+ }
+
+ @Override
+ public void onClosing() {
+ source.dispose();
+ System.exit(0);
+ }
+
+ @Override
+ public void onSettingsOpen() {
+ SettingsDialog dialog = new SettingsDialog(source, true);
+ dialog.setVisible(true);
+ }
+
+ /**
+ * Starts the SmartLoader on the currently loaded document. If a
+ * SmartLoader already exists, it will be stopped.
+ */
+ private void dispatchSmartLoader() {
+ if (smartLoader != null)
+ smartLoader.stop();
+ smartLoader = new SmartLoader(currentDocument);
+ smartLoader.start();
+ }
+
+ /**
+ * Implementation of <code>Thread.UncaughtExceptionHandler</code> to handle unhandled
+ * exceptions. This is used to show an error dialog to the user describing the error
+ * and then routes the error to the instance of the <code>DefaultUnhandledExceptionHandler</code>.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+ private class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ e.printStackTrace(System.err);
+ if (source != null) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ PrintStream out = new PrintStream(os);
+ e.printStackTrace(out);
+ String errorMessage = new String(os.toByteArray());
+ source.showErrorDialog("Unhandled Exception", errorMessage);
+ }
+ DefaultUnhandledExceptionHandler.INSTANCE.uncaughtException(t, e);
+ }
+
+ }
+
+ private class SmartLoader implements Runnable {
+
+ private volatile boolean[] loaded;
+ private volatile boolean[] zoomLoaded;
+ private volatile boolean shouldRun;
+ private Thread thread;
+
+ SmartLoader(Document doc) {
+ loaded = new boolean[doc.size()];
+ zoomLoaded = new boolean[doc.size()];
+ shouldRun = true;
+ }
+
+ void start() {
+ if (thread != null)
+ stop();
+ shouldRun = true;
+ thread = new Thread(this);
+ thread.setDaemon(true);
+ thread.setName("Document-Smart-Loader-Thread");
+ thread.start();
+ }
+
+ void stop() {
+ lock.lock();
+ cv.signalAll();
+ lock.unlock();
+ outOfDate = false;
+ shouldRun = false;
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Thread join interrupted", e);
+ }
+ thread = null;
+ }
+
+ void resetZoom() {
+ for (int i = 0; i < zoomLoaded.length; i++) {
+ zoomLoaded[i] = false;
+ }
+ }
+
+ void signalOutOfDate() {
+ outOfDate = true;
+ lock.lock();
+ try {
+ cv.signalAll();
+ } catch (IllegalMonitorStateException e) {
+ System.err.println("Exception on signaling: " + e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public void run() {
+ System.out.println("Smart loader dispatched.");
+ while (shouldRun) {
+ int currentPage = source.getCurrentPage();
+ int[] toLoad = genToLoad(currentPage);
+
+ if (loaded.length != currentDocument.size())
+ throw new IllegalStateException("Array is size " + loaded.length + " while doc size is " + currentDocument.size());
+
+ int ind = 0;
+ for (int page : toLoad) {
+ if (page >= 1 && page <= currentDocument.size()) {
+ if (source.getZoom() > 1.0) {
+
+ // Load the zoomed page view only if it has not already been loaded.
+ if (!zoomLoaded[page - 1]) {
+ currentDocument.zoomArea(Document.OPERATION_WAIT, page, source.getZoom());
+ zoomLoaded[page - 1] = true;
+ }
+ } else {
+
+ // Unload any zoomed image to save memory consumption
+ currentDocument.unloadZoomed(page);
+
+ // Load the high-resolution page view only if it has not already been loaded
+ if (!loaded[page - 1]) {
+ currentDocument.loadHighRes(Document.OPERATION_WAIT, page);
+ loaded[page - 1] = true;
+ }
+ }
+ }
+ ind++;
+ source.setLoadProgress((int)(((double)ind / toLoad.length) * 100));
+ }
+ source.setLoadProgress(0);
+
+ // First check if the current view is out of date and if so, just immediately continue
+ // so the thread does not get stuck in the lock until another event has occurred.
+ if (!outOfDate) {
+ outOfDate = false;
+ lock.lock();
+ try {
+ cv.await();
+ } catch (InterruptedException e) {
+ System.err.println("Interrupted in smart loader: " + e);
+ } finally {
+ lock.unlock();
+ }
+ } else {
+ outOfDate = false;
+ }
+ }
+ }
+
+ int[] genToLoad(int page) {
+ int range = Settings.SETTINGS.getSetting("preloadRange");
+ int[] arr = new int[range * 2 + 1];
+ for (int i = -range; i <= range; i++) {
+ arr[i + range] = page + i;
+ }
+ return arr;
+ }
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ScrollMap.java b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ScrollMap.java
new file mode 100644
index 00000000..4e0dd5d4
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ScrollMap.java
@@ -0,0 +1,142 @@
+package com.artifex.gsviewer.gui;
+
+import java.awt.Dimension;
+import java.util.Arrays;
+import java.util.Objects;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+
+import com.artifex.gsviewer.Document;
+
+/**
+ * A ScrollMap stores information on how far down a scroll bar
+ * a certain page is in a viewer.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public class ScrollMap {
+
+ private final Document document; // The document which is being viewed
+ private final ViewerWindow window; // The window containing the scroll pane
+ private final int gap; // The gap in between each page
+ private int[] scrollMap; // A map mapping page indices to scroll values
+
+ /**
+ * Creates and generates a new ScrollMap at zoom 1.0.
+ *
+ * @param document The document to generate the map from.
+ * @param window The viewer window to receive scroll panes from.
+ * @param gap The gap in between pages.
+ */
+ public ScrollMap(final Document document, final ViewerWindow window, final int gap) {
+ this.document = Objects.requireNonNull(document, "document");
+ this.scrollMap = null;
+ this.window = Objects.requireNonNull(window, "window");
+ this.gap = gap;
+ genMap(1.0);
+ }
+
+ /**
+ * Generates a map at a given zoom amount.
+ *
+ * @param zoom The amount that the document is zoomed in.
+ * @throws IllegalArgumentException If <code>zoom</code> is less than
+ * 0 or greater than 2.
+ */
+ public synchronized void genMap(final double zoom) throws IllegalArgumentException {
+ if (zoom < 0.0 || zoom > 2.0)
+ throw new IllegalArgumentException("0.0 < zoom < 2.0");
+ scrollMap = new int[document.size()];
+ int currentScroll = 0;
+ for (int pageNum = 0; pageNum < document.size(); pageNum++) {
+ final JComponent component = window.getPageComponent(pageNum + 1);
+ if (component == null)
+ throw new NullPointerException("component is null!");
+ final Dimension cSize = component.getSize();
+
+ scrollMap[pageNum] = currentScroll;
+ currentScroll += cSize.height * zoom;
+ currentScroll += gap;
+ }
+ }
+
+ /**
+ * Returns the amount of scroll on the scroll pane at which page
+ * <code>page</code> is visible.
+ *
+ * @param page The page to get the scroll value for.
+ * @return The respective value.
+ * @throws IndexOutOfBoundsException If <code>page</code> is not a page
+ * in the document.
+ */
+ public synchronized int getScroll(int page) throws IndexOutOfBoundsException {
+ if (page < 1 || page > scrollMap.length)
+ throw new IndexOutOfBoundsException("page = " + page);
+ return scrollMap[page - 1];
+ }
+
+ /**
+ * Returns the current page scrolled to in the scroll pane.
+ *
+ * @return The current page scrolled to.
+ */
+ public synchronized int getCurrentPage() {
+ final JScrollPane scrollPane = window.getViewerScrollPane();
+ final JScrollBar vScrollBar = scrollPane.getVerticalScrollBar();
+ final int scrollValue = vScrollBar.getValue();
+ return getPageFor(scrollValue);
+ }
+
+ /**
+ * Returns the page for a given scroll value.
+ *
+ * @param scroll The scroll value to get the page for.
+ * @return The respective page.
+ */
+ public synchronized int getPageFor(int scroll) {
+ for (int i = 0; i < scrollMap.length; i++) {
+ if (scroll < scrollMap[i])
+ return i; /* Not i + 1! */
+ }
+ return scrollMap.length;
+ }
+
+ /**
+ * Automatically scrolls the scroll pane inside the viewer to the
+ * given page.
+ *
+ * @param page The page to srcoll to.
+ * @throws IndexOutOfBoundsException When <code>page</code> is not in
+ * the document.
+ */
+ public synchronized void scrollTo(int page) throws IndexOutOfBoundsException {
+ if (page < 1 || page > scrollMap.length)
+ throw new IndexOutOfBoundsException("page = " + page);
+ final int scroll = scrollMap[page - 1];
+ final JScrollPane scrollPane = window.getViewerScrollPane();
+ final JScrollBar vScrollBar = scrollPane.getVerticalScrollBar();
+ vScrollBar.setValue(scroll);
+ }
+
+ /**
+ * Returns a copy of the array backing the scroll map, or
+ * <code>null</code> if none has been generated.
+ *
+ * @return A copy of the scroll map's backing array.
+ */
+ public synchronized int[] getMap() {
+ if (scrollMap == null)
+ return null;
+ final int[] copy = new int[this.scrollMap.length];
+ System.arraycopy(scrollMap, 0, copy, 0, scrollMap.length);
+ return copy;
+ }
+
+ @Override
+ public String toString() {
+ return "ScrollMap[map=" + Arrays.toString(scrollMap) + "]";
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/gui/SettingsDialog.java b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/SettingsDialog.java
new file mode 100644
index 00000000..a4ee5d82
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/SettingsDialog.java
@@ -0,0 +1,241 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.artifex.gsviewer.gui;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import com.artifex.gsviewer.Settings;
+
+/**
+ * The settings dialog
+ *
+ * @author Ethan Vrhel
+ */
+public class SettingsDialog extends javax.swing.JDialog {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates new form SettingsDialog
+ */
+ public SettingsDialog(java.awt.Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ setLocationRelativeTo(parent);
+
+ scrollSensitivitySlider.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ scrollSensitvityField
+ .setText(new StringBuilder().append(scrollSensitivitySlider.getValue()).toString());
+ }
+ });
+
+ init();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">
+ private void initComponents() {
+
+ scrollSensitivityLabel = new javax.swing.JLabel();
+ antialiasingCheckbox = new javax.swing.JCheckBox();
+ cancelButton = new javax.swing.JButton();
+ applyButton = new javax.swing.JButton();
+ okButton = new javax.swing.JButton();
+ preloadRangeLabel = new javax.swing.JLabel();
+ scrollSensitivitySlider = new javax.swing.JSlider();
+ scrollSensitvityField = new javax.swing.JTextField();
+ preloadRangeSpinner = new javax.swing.JSpinner();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle("Settings");
+ setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
+ setResizable(false);
+
+ scrollSensitivityLabel.setText("Scroll Sensitivity");
+
+ antialiasingCheckbox.setText("Antialiasing");
+ antialiasingCheckbox.setHideActionText(true);
+ antialiasingCheckbox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
+ antialiasingCheckbox.setMargin(new java.awt.Insets(0, 0, 0, 0));
+
+ cancelButton.setText("Cancel");
+ cancelButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButtonActionPerformed(evt);
+ }
+ });
+
+ applyButton.setText("Apply");
+ applyButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ applyButtonActionPerformed(evt);
+ }
+ });
+
+ okButton.setText("OK");
+ okButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButtonActionPerformed(evt);
+ }
+ });
+
+ preloadRangeLabel.setText("Preload Range");
+
+ scrollSensitivitySlider.setMaximum(200);
+ scrollSensitivitySlider.setMinimum(1);
+ scrollSensitivitySlider.setToolTipText("The number of pixels to scroll");
+
+ scrollSensitvityField.addKeyListener(new java.awt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(java.awt.event.KeyEvent evt) {
+ scrollSensitvityFieldKeyPressed(evt);
+ }
+ });
+
+ preloadRangeSpinner.setToolTipText("The range for loading out of view pages");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout
+ .createSequentialGroup().addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout
+ .createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(scrollSensitivityLabel).addComponent(preloadRangeLabel)
+ .addComponent(antialiasingCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 79,
+ javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(43, 43, 43)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(scrollSensitivitySlider, javax.swing.GroupLayout.PREFERRED_SIZE,
+ 126, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(scrollSensitvityField, javax.swing.GroupLayout.DEFAULT_SIZE, 69,
+ Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(preloadRangeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 40,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, Short.MAX_VALUE))))
+ .addGroup(
+ layout.createSequentialGroup().addComponent(cancelButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(applyButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 51,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(3, 3, 3)))
+ .addContainerGap()));
+ layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout
+ .createSequentialGroup().addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup().addComponent(scrollSensitivityLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(preloadRangeLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(antialiasingCheckbox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(cancelButton).addComponent(applyButton).addComponent(okButton)))
+ .addGroup(layout.createSequentialGroup().addGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(scrollSensitivitySlider, javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(scrollSensitvityField, javax.swing.GroupLayout.Alignment.TRAILING,
+ javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(preloadRangeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
+
+ pack();
+ }// </editor-fold>
+
+ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ apply();
+ dispose();
+ }
+
+ private void applyButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ apply();
+ }
+
+ private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ dispose();
+ }
+
+ private void scrollSensitvityFieldKeyPressed(java.awt.event.KeyEvent evt) {
+ try {
+ int val = Integer.parseInt(scrollSensitvityField.getText());
+ val = Math.max(Math.min(val, 200), 1);
+ scrollSensitivitySlider.setValue(val);
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ // Variables declaration - do not modify
+ private javax.swing.JCheckBox antialiasingCheckbox;
+ private javax.swing.JButton applyButton;
+ private javax.swing.JButton cancelButton;
+ private javax.swing.JButton okButton;
+ private javax.swing.JLabel preloadRangeLabel;
+ private javax.swing.JSpinner preloadRangeSpinner;
+ private javax.swing.JLabel scrollSensitivityLabel;
+ private javax.swing.JSlider scrollSensitivitySlider;
+ private javax.swing.JTextField scrollSensitvityField;
+ // End of variables declaration
+
+ private void init() {
+ Settings settings = Settings.SETTINGS;
+ int scrollSens = settings.getSetting("scrollSens");
+ int preloadRange = settings.getSetting("preloadRange");
+ boolean antialiasing = settings.getSetting("antialiasing");
+
+ scrollSensitvityField.setText(new StringBuilder().append(scrollSens).toString());
+ scrollSensitivitySlider.setValue(scrollSens);
+
+ preloadRangeSpinner.setValue(preloadRange);
+
+ antialiasingCheckbox.setSelected(antialiasing);
+ }
+
+ private void apply() {
+ Settings settings = Settings.SETTINGS;
+ Integer scrollSens = settings.getSetting("scrollSens");
+ Integer preloadRange = settings.getSetting("preloadRange");
+ Boolean antialiasing = settings.getSetting("antialiasing");
+
+ try {
+ scrollSens = Integer.parseInt(scrollSensitvityField.getText());
+ } catch (NumberFormatException e) {
+ }
+
+ try {
+ int set = (Integer) preloadRangeSpinner.getValue();
+ preloadRange = set >= 0 ? set : 0;
+ } catch (ClassCastException e) {
+ }
+
+ antialiasing = antialiasingCheckbox.isSelected();
+
+ settings.setSetting("scrollSens", scrollSens);
+ settings.setSetting("preloadRange", preloadRange);
+ settings.setSetting("antialiasing", antialiasing);
+ }
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerGUIListener.java b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerGUIListener.java
new file mode 100644
index 00000000..5a169731
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerGUIListener.java
@@ -0,0 +1,61 @@
+package com.artifex.gsviewer.gui;
+
+/**
+ * This interface provides several methods which are used to listen
+ * for events on a <code>ViewerWindow</code>.
+ *
+ * @author Ethan Vrhel
+ *
+ */
+public interface ViewerGUIListener {
+
+ /**
+ * Called when this listener is added to a <code>ViewerWindow</code>.
+ *
+ * @param source The window added to.
+ */
+ public void onViewerAdd(ViewerWindow source);
+
+ /**
+ * Called when the user scrolls to a new page.
+ *
+ * @param oldPage The old page.
+ * @param newPage The new page.
+ */
+ public void onPageChange(int oldPage, int newPage);
+
+ /**
+ * Called when the zoom value changes.
+ *
+ * @param oldZoom The old zoom value.
+ * @param newZoom The new zoom value.
+ */
+ public void onZoomChange(double oldZoom, double newZoom);
+
+ /**
+ * Called when the user scrolls.
+ *
+ * @param newScroll The scroll value which the user scrolls to.
+ */
+ public void onScrollChange(int newScroll);
+
+ /**
+ * Called when a file is opened.
+ */
+ public void onOpenFile();
+
+ /**
+ * Called when a file is closed.
+ */
+ public void onCloseFile();
+
+ /**
+ * Called when the window is closing.
+ */
+ public void onClosing();
+
+ /**
+ * Called when the settings window opens.
+ */
+ public void onSettingsOpen();
+}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerWindow.java b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerWindow.java
new file mode 100644
index 00000000..48b39953
--- /dev/null
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/gui/ViewerWindow.java
@@ -0,0 +1,1020 @@
+package com.artifex.gsviewer.gui;
+
+import java.awt.Adjustable;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.AdjustmentEvent;
+import java.awt.image.BufferedImage;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
+import com.artifex.gsviewer.Document;
+import com.artifex.gsviewer.Page;
+import com.artifex.gsviewer.PageUpdateCallback;
+import com.artifex.gsviewer.Settings;
+
+/**
+ * <p>Used to display documents into a window.</p>
+ *
+ * <p>Partially a auto-generated form using NetBeans.</p>
+ */
+public class ViewerWindow extends javax.swing.JFrame {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The gap between each page in the main viewer, in pixels.
+ */
+ public static final int VIEWER_PAGE_GAP = 10;
+
+ /**
+ * The gap between each page in the mini viewer, in pixels.
+ */
+ public static final int MINI_VIEWER_PAGE_GAP = 10;
+
+ /**
+ * Constant indicating the "Yes" option was clicked in a dialog.
+ */
+ public static final int YES = JOptionPane.YES_OPTION;
+
+ /**
+ * Constant indicating the "No" option was clicked in a dialog.
+ */
+ public static final int NO = JOptionPane.NO_OPTION;
+
+ /**
+ * Constant indicating the "Cancel" option was clicked in a ddialog.
+ */
+ public static final int CANCEL = JOptionPane.CANCEL_OPTION;
+
+ private ViewerGUIListener guiListener; // The ViewerGUIListener to receive callbacks
+ private int currentPage, maxPage; // Current page displayed and the length of the document
+ private double currentZoom; // The amount the viewer is zoomed
+
+ private Document loadedDocument; // The currently loaded document
+ private ScrollMap scrollMap; // The ScrollMap mapping scroll values to page numbers
+ private List<PagePanel> viewerPagePanels; // A list of the page panels in the viewer
+ private List<PagePanel> miniViewerPagePanels; // A list of the page panels in the mini viewer
+
+ private Dimension min; // The minimum window size
+ private Dimension max; // The maximum window size
+
+ private boolean gotoPage; // Whether the viewer should jump to currentPage
+
+ private boolean isLoading;
+
+ /**
+ * Creates new ViewerWindow.
+ */
+ public ViewerWindow() {
+ this(null);
+ }
+
+ /**
+ * Creates a new ViewerWindow with a GUIListener.
+ *
+ * @param listener A ViewerGUIListener which will receive callbacks regarding
+ * different events.
+ */
+ public ViewerWindow(final ViewerGUIListener listener) {
+ initComponents();
+ this.currentPage = 0;
+ this.maxPage = 0;
+ this.currentZoom = 1.0;
+ this.viewerPagePanels = new ArrayList<>();
+ this.miniViewerPagePanels = new ArrayList<>();
+
+ // Adjustment listener looks for any change in the scroll value of the scrollbar
+ this.viewerScrollPane.getVerticalScrollBar().addAdjustmentListener((AdjustmentEvent evt) -> {
+ this.viewerScrollPane.getVerticalScrollBar().setUnitIncrement(Settings.SETTINGS.getSetting("scrollSens"));
+ if (scrollMap != null) {
+ Adjustable adjustable = evt.getAdjustable();
+ int currentPage = scrollMap.getPageFor(adjustable.getValue());
+ if (ViewerWindow.this.currentPage != currentPage) {
+ if (guiListener != null)
+ guiListener.onPageChange(ViewerWindow.this.currentPage, currentPage);
+ }
+ if (guiListener != null)
+ guiListener.onScrollChange(adjustable.getValue());
+ ViewerWindow.this.currentPage = currentPage;
+ assumePage(currentPage);
+ }
+ refreshButtons();
+ });
+
+ setGUIListener(listener);
+
+ zoomSlider.setEnabled(false);
+ increaseZoomButton.setEnabled(false);
+ decreaseZoomButton.setEnabled(false);
+ zoomSlider.setValue(50);
+
+ nextPageButton.setEnabled(false);
+ lastPageButton.setEnabled(false);
+ pageNumberField.setEditable(false);
+
+ setLocationRelativeTo(null);
+
+ min = getMinimumSize();
+ max = getMaximumSize();
+
+ gotoPage = false;
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">
+ private void initComponents() {
+
+ viewerScrollPane = new javax.swing.JScrollPane();
+ viewerContentPane = new javax.swing.JPanel();
+ miniViewerScrollPane = new javax.swing.JScrollPane();
+ miniViewerContentPane = new javax.swing.JPanel();
+ toolbarPanel = new javax.swing.JPanel();
+ decreaseZoomButton = new javax.swing.JButton();
+ zoomSlider = new javax.swing.JSlider();
+ increaseZoomButton = new javax.swing.JButton();
+ progressBar = new javax.swing.JProgressBar();
+ lastPageButton = new javax.swing.JButton();
+ pageNumberField = new javax.swing.JTextField();
+ pageSlashLabel = new javax.swing.JLabel();
+ maxPagesLabel = new javax.swing.JTextField();
+ nextPageButton = new javax.swing.JButton();
+ menuBar = new javax.swing.JMenuBar();
+ fileMenu = new javax.swing.JMenu();
+ openMenu = new javax.swing.JMenuItem();
+ closeMenuItem = new javax.swing.JMenuItem();
+ fileMenuSeparator = new javax.swing.JPopupMenu.Separator();
+ exitMenuItem = new javax.swing.JMenuItem();
+ editMenu = new javax.swing.JMenu();
+ settingsMenuItem = new javax.swing.JMenuItem();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
+ setTitle("Viewer");
+ setMinimumSize(new java.awt.Dimension(640, 650));
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ formWindowClosing(evt);
+ }
+ });
+
+ viewerScrollPane.setMinimumSize(new java.awt.Dimension(85, 110));
+
+ javax.swing.GroupLayout viewerContentPaneLayout = new javax.swing.GroupLayout(viewerContentPane);
+ viewerContentPane.setLayout(viewerContentPaneLayout);
+ viewerContentPaneLayout.setHorizontalGroup(
+ viewerContentPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 623, Short.MAX_VALUE)
+ );
+ viewerContentPaneLayout.setVerticalGroup(
+ viewerContentPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 639, Short.MAX_VALUE)
+ );
+
+ viewerScrollPane.setViewportView(viewerContentPane);
+
+ miniViewerScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+
+ javax.swing.GroupLayout miniViewerContentPaneLayout = new javax.swing.GroupLayout(miniViewerContentPane);
+ miniViewerContentPane.setLayout(miniViewerContentPaneLayout);
+ miniViewerContentPaneLayout.setHorizontalGroup(
+ miniViewerContentPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 118, Short.MAX_VALUE)
+ );
+ miniViewerContentPaneLayout.setVerticalGroup(
+ miniViewerContentPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 639, Short.MAX_VALUE)
+ );
+
+ miniViewerScrollPane.setViewportView(miniViewerContentPane);
+
+ decreaseZoomButton.setText("-");
+ decreaseZoomButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ decreaseZoomButtonActionPerformed(evt);
+ }
+ });
+
+ zoomSlider.setMajorTickSpacing(25);
+ zoomSlider.setMinorTickSpacing(5);
+ zoomSlider.setPaintTicks(true);
+ zoomSlider.setSnapToTicks(true);
+ zoomSlider.addMouseListener(new java.awt.event.MouseAdapter() {
+ @Override
+ public void mouseReleased(java.awt.event.MouseEvent evt) {
+ zoomSliderMouseReleased(evt);
+ }
+ });
+
+ increaseZoomButton.setText("+");
+ increaseZoomButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ increaseZoomButtonActionPerformed(evt);
+ }
+ });
+
+ lastPageButton.setText("<");
+ lastPageButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ lastPageButtonActionPerformed(evt);
+ }
+ });
+
+ pageNumberField.setText("0");
+ pageNumberField.addKeyListener(new java.awt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(java.awt.event.KeyEvent evt) {
+ pageNumberFieldKeyPressed(evt);
+ }
+ });
+
+ pageSlashLabel.setText("/");
+
+ maxPagesLabel.setEditable(false);
+ maxPagesLabel.setText("0");
+
+ nextPageButton.setText(">");
+ nextPageButton.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ nextPageButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout toolbarPanelLayout = new javax.swing.GroupLayout(toolbarPanel);
+ toolbarPanel.setLayout(toolbarPanelLayout);
+ toolbarPanelLayout.setHorizontalGroup(
+ toolbarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(toolbarPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(toolbarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(toolbarPanelLayout.createSequentialGroup()
+ .addComponent(decreaseZoomButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(zoomSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 111, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(increaseZoomButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(lastPageButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pageNumberField, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pageSlashLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(maxPagesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(nextPageButton))
+ .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ toolbarPanelLayout.setVerticalGroup(
+ toolbarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(toolbarPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(toolbarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(toolbarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(increaseZoomButton)
+ .addComponent(lastPageButton)
+ .addComponent(pageNumberField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(pageSlashLabel)
+ .addComponent(maxPagesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(nextPageButton))
+ .addComponent(zoomSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(decreaseZoomButton))
+ .addGap(17, 17, 17)
+ .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ fileMenu.setText("File");
+
+ openMenu.setText("Open");
+ openMenu.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ openMenuActionPerformed(evt);
+ }
+ });
+ fileMenu.add(openMenu);
+
+ closeMenuItem.setText("Close");
+ closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ closeMenuItemActionPerformed(evt);
+ }
+ });
+ fileMenu.add(closeMenuItem);
+ fileMenu.add(fileMenuSeparator);
+
+ exitMenuItem.setText("Exit");
+ exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ exitMenuItemActionPerformed(evt);
+ }
+ });
+ fileMenu.add(exitMenuItem);
+
+ menuBar.add(fileMenu);
+
+ editMenu.setText("Edit");
+
+ settingsMenuItem.setText("Settings");
+ settingsMenuItem.addActionListener(new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ settingsMenuItemActionPerformed(evt);
+ }
+ });
+ editMenu.add(settingsMenuItem);
+
+ menuBar.add(editMenu);
+
+ setJMenuBar(menuBar);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(miniViewerScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(toolbarPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(viewerScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 642, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(miniViewerScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 592, Short.MAX_VALUE)
+ .addComponent(viewerScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 592, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(toolbarPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+
+ pack();
+ }// </editor-fold>
+
+ private void lastPageButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_lastPageButtonActionPerformed
+ if (maxPage > 0) {
+ tryChangePage(currentPage - 1);
+ } else {
+ pageNumberField.setText(new StringBuilder().append(0).toString());
+ }
+ }// GEN-LAST:event_lastPageButtonActionPerformed
+
+ private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_nextPageButtonActionPerformed
+ if (maxPage > 0) {
+ tryChangePage(currentPage + 1);
+ } else {
+ pageNumberField.setText(new StringBuilder().append(0).toString());
+ }
+ }// GEN-LAST:event_nextPageButtonActionPerformed
+
+ private void formWindowClosing(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_formWindowClosing
+ if (guiListener != null)
+ guiListener.onClosing();
+ }// GEN-LAST:event_formWindowClosing
+
+ private void pageNumberFieldKeyPressed(java.awt.event.KeyEvent evt) {// GEN-FIRST:event_pageNumberFieldKeyPressed
+ if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
+ try {
+ final String text = pageNumberField.getText();
+ tryChangePage(Integer.parseInt(text));
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid page numer.");
+ }
+ }
+ }// GEN-LAST:event_pageNumberFieldKeyPressed
+
+ private void zoomSliderMouseReleased(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_zoomSliderMouseReleased
+ tryChangeZoom(zoomSlider.getValue() / 50.0);
+ }// GEN-LAST:event_zoomSliderMouseReleased
+
+ private void increaseZoomButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_increaseZoomButtonActionPerformed
+ if (tryChangeZoom(Math.min(Math.ceil((currentZoom * 10) + 1) / 10, 2.0)))
+ zoomSlider.setValue((int)(currentZoom * 50));
+ }// GEN-LAST:event_increaseZoomButtonActionPerformed
+
+ private void decreaseZoomButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_decreaseZoomButtonActionPerformed
+ if (tryChangeZoom(Math.max(Math.floor((currentZoom * 10) - 1) / 10, 0.0)))
+ zoomSlider.setValue((int)(currentZoom * 50));
+ }// GEN-LAST:event_decreaseZoomButtonActionPerformed
+
+ private void openMenuActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_openMenuActionPerformed
+ if (guiListener != null)
+ guiListener.onOpenFile();
+ }// GEN-LAST:event_openMenuActionPerformed
+
+ private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_closeMenuItemActionPerformed
+ if (guiListener != null)
+ guiListener.onCloseFile();
+ }// GEN-LAST:event_closeMenuItemActionPerformed
+
+ private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_exitMenuItemActionPerformed
+ if (guiListener != null)
+ guiListener.onClosing();
+ }// GEN-LAST:event_exitMenuItemActionPerformed
+
+ private void settingsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_settingsMenuItemActionPerformed
+ if (guiListener != null)
+ guiListener.onSettingsOpen();
+ tryChangeZoom(0.1);
+ }// GEN-LAST:event_settingsMenuItemActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JMenuItem closeMenuItem;
+ private javax.swing.JButton decreaseZoomButton;
+ private javax.swing.JMenu editMenu;
+ private javax.swing.JMenuItem exitMenuItem;
+ private javax.swing.JMenu fileMenu;
+ private javax.swing.JPopupMenu.Separator fileMenuSeparator;
+ private javax.swing.JButton increaseZoomButton;
+ private javax.swing.JButton lastPageButton;
+ private javax.swing.JTextField maxPagesLabel;
+ private javax.swing.JMenuBar menuBar;
+ private javax.swing.JPanel miniViewerContentPane;
+ private javax.swing.JScrollPane miniViewerScrollPane;
+ private javax.swing.JButton nextPageButton;
+ private javax.swing.JMenuItem openMenu;
+ private javax.swing.JTextField pageNumberField;
+ private javax.swing.JLabel pageSlashLabel;
+ private javax.swing.JProgressBar progressBar;
+ private javax.swing.JMenuItem settingsMenuItem;
+ private javax.swing.JPanel toolbarPanel;
+ private javax.swing.JPanel viewerContentPane;
+ private javax.swing.JScrollPane viewerScrollPane;
+ private javax.swing.JSlider zoomSlider;
+ // End of variables declaration//GEN-END:variables
+
+ private class PagePanel extends JPanel implements PageUpdateCallback {
+
+ static final long serialVersionUID = 1L;
+
+ Object lock; // A lock to ensure multiple draw calls don't happen
+ Page page; // The page to display
+ double size; // The size of the page
+
+ Image toDraw; // The image which should be drawn by the panel
+
+ /**
+ * Creates a new page panel to display a page of a document.
+ *
+ * @param page The page to display.
+ * @param size The size of the page.
+ */
+ PagePanel(final Page page, double size) {
+ this.lock = new Object();
+ this.page = page;
+ this.size = size == 0.0 ? 0.01 : size;
+
+ Dimension pageSize = page.getSize();
+
+ Dimension actualSize = new Dimension((int)(pageSize.width * size),
+ (int)(pageSize.height * size));
+
+ toDraw = getImage();
+
+ setPreferredSize(actualSize);
+ setMaximumSize(actualSize);
+
+ setBackground(Color.WHITE);
+
+ setDoubleBuffered(false);
+ //pack();
+
+ page.addCallback(this);
+ }
+
+ /**
+ * Returns the image which should be displayed in the viewer. This will
+ * change depending on the availability of high resolution images and zoom
+ * values.
+ *
+ * @return The image which should be displayed in the viewer.
+ */
+ Image getImage() {
+ if (page != null && page.getLowResImage() != null) {
+ Dimension pageSize = page.getSize();
+ Dimension actualSize = new Dimension((int)(pageSize.width * size),
+ (int)(pageSize.height * size));
+ BufferedImage img = page.getDisplayableImage();
+ if (page.getZoomedImage() != null && size > 1.0)
+ img = page.getZoomedImage();
+
+ Image result = img;
+ if (img == page.getLowResImage() || currentZoom < 1.0 ||
+ (img == page.getHighResImage() && currentZoom > 1.0 && page.getZoomedImage() == null)) {
+ result = img.getScaledInstance(actualSize.width, actualSize.height, Image.SCALE_SMOOTH);
+ }
+ return result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Cleans up this page panel.
+ */
+ void cleanup() {
+ if (page != null) {
+ page.removeCallback(this);
+ page = null;
+ }
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ synchronized (lock) {
+ if (toDraw != null) {
+ g.drawImage(toDraw, 0, 0, this);
+ }
+ }
+ }
+
+ @Override
+ public void onPageUpdate() {
+ toDraw = getImage();
+ SwingUtilities.invokeLater(() -> {
+ repaint();
+ });
+ }
+
+ @Override
+ public void onLoadLowRes() { }
+
+ @Override
+ public void onUnloadLowRes() { }
+
+ @Override
+ public void onLoadHighRes() { }
+
+ @Override
+ public void onUnloadHighRes() { }
+
+ @Override
+ public void onLoadZoomed() { }
+
+ @Override
+ public void onUnloadZoomed() { }
+ }
+
+ /**
+ * The action listener to listen for button clicks in the
+ * mini viewer. Clicking on a button in the mini viewer will jump
+ * the user's view to the respective page.
+ *
+ * @author evrhe
+ *
+ */
+ private class MiniViewerActionListener implements ActionListener {
+
+ final int pageNum; // The assigned page number for this listener
+
+ /**
+ * Creates a new listener with a tied page.
+ *
+ * @param pageNum The page number tied to this listener.
+ */
+ MiniViewerActionListener(int pageNum) {
+ this.pageNum = pageNum;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ tryChangePage(pageNum);
+ }
+
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+ if (this.scrollMap != null) {
+ assumePage(this.currentPage = this.scrollMap.getCurrentPage());
+ if (gotoPage)
+ scrollMap.scrollTo(currentPage);
+ }
+ unlockSize();
+ gotoPage = false;
+ }
+
+ /**
+ * Sets the ViewerGUIListener the window should use.
+ *
+ * @param listener A listener.
+ */
+ public void setGUIListener(final ViewerGUIListener listener) {
+ this.guiListener = listener;
+ listener.onViewerAdd(this);
+ }
+
+ /**
+ * Sets the progress of the progress bar in the window.
+ *
+ * @param progress The amount of progress (0-100).
+ */
+ public void setLoadProgress(final int progress) {
+ progressBar.setValue(progress);
+ }
+
+ /**
+ * Loads a document into the viewer and unloads the currently loaded document
+ * if one is loaded.
+ *
+ * @param document The document to load into the viewer.
+ */
+ public void loadDocumentToViewer(final Document document) {
+ isLoading = true;
+ try {
+ unloadViewerDocument();
+ if (document == null)
+ return;
+ lockSize();
+
+ this.loadedDocument = document;
+ viewerContentPane.setLayout(new BoxLayout(viewerContentPane, BoxLayout.Y_AXIS));
+
+ // Generate the viewer page components
+ /*for (final Page page : document) {
+ final PagePanel panel = new PagePanel(page, 1.0);
+ viewerContentPane.add(panel);
+ viewerContentPane.add(Box.createVerticalStrut(VIEWER_PAGE_GAP));
+
+ viewerPagePanels.add(panel);
+ }*/
+
+ miniViewerContentPane.setLayout(new BoxLayout(miniViewerContentPane, BoxLayout.Y_AXIS));
+
+ int height = 0;
+ // Generate the mini viewer icons
+ int pageNum = 1;
+ for (final Page page : document) {
+
+ final PagePanel panel = new PagePanel(page, 1.0);
+ viewerContentPane.add(panel);
+ viewerContentPane.add(Box.createVerticalStrut(VIEWER_PAGE_GAP));
+
+ viewerPagePanels.add(panel);
+ height += page.getSize().height;
+ height += VIEWER_PAGE_GAP;
+
+ ImageIcon icon = new ImageIcon(page.getLowResImage());
+ JButton button = new JButton(icon);
+ button.setPreferredSize(page.getLowResSize());
+ button.addActionListener(new MiniViewerActionListener(pageNum++));
+ button.setFocusable(false);
+
+ miniViewerContentPane.add(button);
+ miniViewerContentPane.add(Box.createVerticalStrut(MINI_VIEWER_PAGE_GAP));
+ }
+ System.out.println(height);
+
+ // Generate the scroll map
+ invokeAndWait(() -> {
+ revalidate();
+ this.scrollMap = new ScrollMap(document, this, VIEWER_PAGE_GAP);
+ });
+ assumePage(this.currentPage = 1);
+ assumeMaxPages(this.maxPage = document.size());
+
+ setTitle("Viewer - " + document.getName());
+
+ // Enable all widgets
+ zoomSlider.setEnabled(true);
+ increaseZoomButton.setEnabled(true);
+ decreaseZoomButton.setEnabled(true);
+ zoomSlider.setValue(50);
+ zoomSlider.setFocusable(true);
+
+ nextPageButton.setEnabled(true);
+ lastPageButton.setEnabled(true);
+ pageNumberField.setEditable(true);
+
+ refreshButtons();
+ } finally {
+ isLoading = false;
+ }
+ }
+
+ /**
+ * Unloads the currently loaded document from the viewer. If no document
+ * is loaded, this method does nothing.
+ */
+ public void unloadViewerDocument() {
+ if (this.loadedDocument == null)
+ return;
+
+ lockSize();
+
+ this.loadedDocument = null;
+ this.scrollMap = null;
+
+ // Disable all widgets
+ this.assumePage(0);
+ this.assumeMaxPages(0);
+ this.zoomSlider.setValue(50);
+ this.zoomSlider.setEnabled(false);
+ this.zoomSlider.setFocusable(false);
+ this.pageNumberField.setEditable(false);
+
+ setTitle("Viewer");
+
+ // Remove all pages
+ for (final PagePanel panel : viewerPagePanels) {
+ synchronized (panel.lock) {
+ panel.cleanup();
+ }
+ }
+ viewerContentPane.removeAll();
+ viewerPagePanels.clear();
+
+ miniViewerContentPane.removeAll();
+ miniViewerPagePanels.clear();
+
+ System.gc();
+
+ invokeAndWait(() -> {
+ viewerContentPane.revalidate();
+ viewerContentPane.repaint();
+
+ miniViewerContentPane.revalidate();
+ miniViewerContentPane.repaint();
+ });
+
+ }
+
+ /**
+ * Returns the document currently loaded in the viewer.
+ *
+ * @return The currently loaded document, or <code>null</code> if none
+ * is loaded.
+ */
+ public Document getLoadedDocument() {
+ return loadedDocument;
+ }
+
+ /**
+ * Returns the respective component inside of the viewer for a page.
+ *
+ * @param pageNum The page to get the component for.
+ * @return The respective component.
+ * @throws IndexOutOfBoundsException If <code>pageNum</code> is not a page in the document.
+ */
+ public JComponent getPageComponent(final int pageNum) throws IndexOutOfBoundsException {
+ return viewerPagePanels.get(pageNum - 1);
+ }
+
+ /**
+ * Returns the scroll pane used by the viewer.
+ *
+ * @return The scroll pane.
+ */
+ public JScrollPane getViewerScrollPane() {
+ return viewerScrollPane;
+ }
+
+ /**
+ * Tries to change the page to another page.
+ *
+ * @param newPage The page to change to.
+ * @return <code>true</code> if the page is a valid page and <code>false</code>
+ * otherwise.
+ */
+ public boolean tryChangePage(final int newPage) {
+ if (newPage < 1 || newPage > maxPage)
+ return false;
+ if (newPage != currentPage) {
+ final int oldPage = currentPage;
+ this.currentPage = newPage;
+ if (guiListener != null)
+ guiListener.onPageChange(oldPage, currentPage);
+ if (this.scrollMap != null) {
+ scrollMap.scrollTo(newPage);
+ assumePage(newPage);
+ }
+
+ refreshButtons();
+
+ pageNumberField.setText(new StringBuilder().append(currentPage).toString());
+ }
+ return true;
+ }
+
+ /**
+ * Tries to change the zoom to another zoom value.
+ *
+ * @param newZoom The zoom to change to.
+ * @return <code>true</code> if the zoom is a valid zoom value and
+ * <code>false</code> otherwise.
+ */
+ public boolean tryChangeZoom(final double newZoom) {
+ if (newZoom < 0 || newZoom > 2)
+ return false;
+ if (newZoom != currentZoom) {
+ gotoPage = true;
+ final double oldZoom = currentZoom;
+ this.currentZoom = newZoom;
+ if (guiListener != null)
+ guiListener.onZoomChange(oldZoom, currentZoom);
+ if (this.scrollMap != null) {
+ redisplayDocument();
+ }
+
+ refreshButtons();
+ }
+ return true;
+ }
+
+ /**
+ * Returns the current page the user is scrolled to.
+ *
+ * @return The current page.
+ */
+ public int getCurrentPage() {
+ if (this.scrollMap != null)
+ return scrollMap.getCurrentPage();
+ return 0;
+ }
+
+ /**
+ * Shows an error dialog with a title and message.
+ *
+ * @param title The title of the dialog.
+ * @param message The message of the dialog.
+ * @throws HeadlessException If <code>GraphicsEnvironment.isHeadless</code> returns <code>true</code>.
+ */
+ public void showErrorDialog(String title, String message) throws HeadlessException {
+ JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE);
+ }
+
+ /**
+ * Shows a warning dialog with a title and message.
+ *
+ * @param title The title of the dialog.
+ * @param message The message of the dialog.
+ * @throws HeadlessException If <code>GraphicsEnvironment.isHeadless</code> returns <code>true</code>.
+ */
+ public void showWarningDialog(String title, String message) throws HeadlessException {
+ JOptionPane.showMessageDialog(this, message, title, JOptionPane.WARNING_MESSAGE);
+ }
+
+ /**
+ * Shows a confirmation dialog with a title and message.
+ *
+ * @param title The title of the dialog.
+ * @param message The message of the dialog.
+ * @return The button the user clicked (<code>ViewerWindow.YES</code>, <code>ViewerWindow.NO</code>,
+ * or <code>ViewerWindow.CANCEL</code>).
+ * @throws HeadlessException If <code>GraphicsEnvironment.isHeadless</code> returns <code>true</code>.
+ */
+ public int showConfirmDialog(String title, String message) throws HeadlessException {
+ return JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_CANCEL_OPTION);
+ }
+
+ /**
+ * Returns how much the viewer is zoomed in.
+ *
+ * @return The current zoom.
+ */
+ public double getZoom() {
+ return currentZoom;
+ }
+
+ /**
+ * Returns whether the window is loading a document.
+ *
+ * @return <code>true</code> if the window is loading a document
+ * and <code>false</code> otherwise.
+ */
+ public boolean isLoading() {
+ return isLoading;
+ }
+
+ public void apply(Settings settings) {
+ int sens = settings.getSetting("scrollSens");
+ this.viewerScrollPane.getVerticalScrollBar().setUnitIncrement(sens);
+ this.miniViewerScrollPane.getVerticalScrollBar().setUnitIncrement(sens);
+ }
+
+ /**
+ * Refresh each button's state.
+ */
+ private void refreshButtons() {
+ this.lastPageButton.setEnabled(currentPage != 1 && loadedDocument != null);
+ this.nextPageButton.setEnabled(currentPage != maxPage && loadedDocument != null);
+
+ this.increaseZoomButton.setEnabled(currentZoom != 2.0 && loadedDocument != null);
+ this.decreaseZoomButton.setEnabled(currentZoom != 0.0 && loadedDocument != null);
+ }
+
+ /**
+ * Redisplays the currently loaded document. This will remove all loaded page panels
+ * and recreate them.
+ */
+ private void redisplayDocument() {
+ lockSize();
+
+ for (final PagePanel panel : viewerPagePanels) {
+ synchronized (panel.lock) {
+ panel.cleanup();
+ }
+ }
+ viewerContentPane.removeAll();
+ viewerPagePanels.clear();
+
+ System.gc();
+
+ for (final Page page : loadedDocument) {
+ final PagePanel panel = new PagePanel(page, currentZoom);
+ viewerContentPane.add(panel);
+ viewerContentPane.add(Box.createVerticalStrut(VIEWER_PAGE_GAP));
+
+ viewerPagePanels.add(panel);
+ }
+
+ invokeAndWait(() -> {
+ gotoPage = true;
+ revalidate();
+ scrollMap.genMap(1.0);
+ });
+ }
+
+ /**
+ * Prevents the window from being resized.
+ */
+ private void lockSize() {
+ Dimension size = getSize();
+ setMinimumSize(size);
+ setMaximumSize(size);
+ //setResizable(false);
+ }
+
+ /**
+ * Allows the window to be resized.
+ */
+ private void unlockSize() {
+ setMinimumSize(min);
+ setMaximumSize(max);
+ //setResizable(true);
+ }
+
+ /**
+ * Assume that we are on a certain page by setting the page number field.
+ *
+ * @param pageNum A page number.
+ */
+ private void assumePage(int pageNum) {
+ this.pageNumberField.setText(new StringBuilder().append(pageNum).toString());
+ }
+
+ /**
+ * Assume that we have a certain max page count by setting the max pages field.
+ *
+ * @param pageCount A page count.
+ */
+ private void assumeMaxPages(int pageCount) {
+ this.maxPagesLabel.setText(new StringBuilder().append(pageCount).toString());
+ }
+
+ private void invokeAndWait(Runnable r) {
+ if (!SwingUtilities.isEventDispatchThread()) {
+ try {
+ SwingUtilities.invokeAndWait(r);
+ } catch (InvocationTargetException | InterruptedException e) {
+ r.run();
+ }
+ } else {
+ r.run();
+ }
+ }
+}
diff --git a/demos/java/jni/gs_jni/callbacks.cpp b/demos/java/jni/gs_jni/callbacks.cpp
new file mode 100644
index 00000000..a8ad2196
--- /dev/null
+++ b/demos/java/jni/gs_jni/callbacks.cpp
@@ -0,0 +1,368 @@
+#include "callbacks.h"
+
+#include "jni_util.h"
+
+#include <string.h>
+
+#define STDIN_SIG "(J[BI)I"
+#define STDOUT_SIG "(J[BI)I"
+#define STDERR_SIG "(J[BI)I"
+
+#define POLL_SIG "(J)I"
+
+#define DISPLAY_OPEN_SIG "(JJ)I"
+#define DISPLAY_PRECLOSE_SIG "(JJ)I"
+#define DISPLAY_CLOSE_SIG "(JJ)I"
+#define DISPLAY_PRESIZE_SIG "(JJIIII)I"
+#define DISPLAY_SIZE_SIG "(JJIIIILcom/artifex/gsjava/util/BytePointer;)I"
+#define DISPLAY_SYNC_SIG "(JJ)I"
+#define DISPLAY_PAGE_SIG "(JJIZ)I"
+#define DISPLAY_UPDATE_SIG "(JJIIII)I"
+// display memalloc
+// display memfree
+#define DISPLAY_SEPARATION_SIG "(JJI[BSSSS)I"
+#define DISPLAY_ADJUST_BAND_HEIGHT_SIG "(JJI)I"
+#define DISPLAY_RECTANGLE_REQUEST "(JJLcom/artifex/gsjava/LongReference;Lcom/artifex/gsjava/IntReference;\
+Lcom/artifex/gsjava/IntReference;Lcom/artifex/gsjava/IntReference;Lcom/artifex/gsjava/IntReference;\
+Lcom/artifex/gsjava/IntReference;Lcom/artifex/gsjava/IntReference;Lcom/artifex/gsjava/IntReference;\
+Lcom/artifex/gsjava/IntReference;)I"
+
+#define CHECK_AND_RETURN(E) if (E->ExceptionCheck()) { return -21; }
+
+using namespace util;
+
+static JNIEnv *g_env = NULL;
+
+static jobject g_stdIn = NULL;
+static jobject g_stdOut = NULL;
+static jobject g_stdErr = NULL;
+
+static jobject g_poll = NULL;
+
+static jobject g_displayCallback = NULL;
+
+static jobject g_callout = NULL;
+
+void callbacks::setJNIEnv(JNIEnv *env)
+{
+ g_env = env;
+}
+
+void callbacks::setIOCallbacks(jobject stdIn, jobject stdOut, jobject stdErr)
+{
+ if (g_env)
+ {
+ if (g_stdIn)
+ g_env->DeleteGlobalRef(g_stdIn);
+
+ if (g_stdOut)
+ g_env->DeleteGlobalRef(g_stdOut);
+
+ if (g_stdErr)
+ g_env->DeleteGlobalRef(g_stdErr);
+
+ g_stdIn = g_env->NewGlobalRef(stdIn);
+ g_stdOut = g_env->NewGlobalRef(stdOut);
+ g_stdErr = g_env->NewGlobalRef(stdErr);
+ }
+}
+
+int callbacks::stdInFunction(void *callerHandle, char *buf, int len)
+{
+ int code = 0;
+ if (g_env && g_stdIn)
+ {
+ jbyteArray byteArray = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(byteArray, 0, len, (jbyte *)buf);
+ code = callIntMethod(g_env, g_stdIn, "onStdIn", STDIN_SIG, (jlong)callerHandle, byteArray, (jint)len);
+ }
+ return code;
+}
+
+int callbacks::stdOutFunction(void *callerHandle, const char *str, int len)
+{
+ int code = 0;
+ if (g_env && g_stdOut)
+ {
+ jbyteArray byteArray = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str);
+ code = callIntMethod(g_env, g_stdOut, "onStdOut", STDOUT_SIG, (jlong)callerHandle, byteArray, (jint)len);
+ }
+ return code;
+}
+
+int callbacks::stdErrFunction(void *callerHandle, const char *str, int len)
+{
+ int code = 0;
+ if (g_env && g_stdErr)
+ {
+ jbyteArray byteArray = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str);
+ code = callIntMethod(g_env, g_stdErr, "onStdErr", STDERR_SIG, (jlong)callerHandle, byteArray, (jint)len);
+ }
+ return code;
+}
+
+void callbacks::setPollCallback(jobject poll)
+{
+ if (g_env)
+ {
+ if (g_poll)
+ g_env->DeleteGlobalRef(g_poll);
+
+ g_poll = g_env->NewGlobalRef(poll);
+ }
+}
+
+int callbacks::pollFunction(void *callerHandle)
+{
+ int code = 0;
+ if (g_env && g_poll)
+ {
+ code = callIntMethod(g_env, g_poll, "onPoll", POLL_SIG, (jlong)callerHandle);
+ }
+ return code;
+}
+
+void callbacks::setDisplayCallback(jobject displayCallback)
+{
+ if (g_env)
+ {
+ if (g_displayCallback)
+ {
+ g_env->DeleteGlobalRef(g_displayCallback);
+ g_displayCallback = NULL;
+ }
+
+ g_displayCallback = g_env->NewGlobalRef(displayCallback);
+ //g_displayCallback = displayCallback;
+ }
+}
+
+void callbacks::setCalloutCallback(jobject callout)
+{
+ if (g_env)
+ {
+ if (g_callout)
+ g_env->DeleteGlobalRef(g_callout);
+
+ g_callout = g_env->NewGlobalRef(callout);
+ }
+}
+
+int callbacks::calloutFunction(void *instance, void *handle, const char *deviceName, int id, int size, void *data)
+{
+ int code = 0;
+ if (g_env && g_callout)
+ {
+ jsize len = strlen(deviceName);
+ jbyteArray array = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(array, 0, len, (const jbyte *)deviceName);
+ code = callIntMethod(g_env, g_callout, "onCallout", "(JJ[BIIJ)I", (jlong)instance, (jlong)handle, array, id, size, (jlong)data);
+ }
+ return code;
+}
+
+int callbacks::display::displayOpenFunction(void *handle, void *device)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ jclass clazz = g_env->GetObjectClass(g_displayCallback);
+ const char *name = getClassName(g_env, clazz);
+ freeClassName(name);
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayOpen", DISPLAY_OPEN_SIG, (jlong)handle, (jlong)device);
+ CHECK_AND_RETURN(g_env);
+ }
+ return 0;
+}
+
+int callbacks::display::displayPrecloseFunction(void *handle, void *device)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayPreclose", DISPLAY_PRECLOSE_SIG, (jlong)handle, (jlong)device);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayCloseFunction(void *handle, void *device)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayClose", DISPLAY_CLOSE_SIG, (jlong)handle, (jlong)device);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayPresizeFunction(void *handle, void *device, int width, int height, int raster, unsigned int format)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayPresize", DISPLAY_PRESIZE_SIG, (jlong)handle,
+ (jlong)device, width, height, raster, (jint)format);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displaySizeFunction(void *handle, void *device, int width, int height, int raster,
+ unsigned int format, unsigned char *pimage)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ jsize len = height * raster;
+ jbyteArray byteArray = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(byteArray, 0, len, (signed char *)pimage);
+
+ static const char *const bytePointerClassName = "com/artifex/gsjava/util/BytePointer";
+ static const char *const nativePointerClassName = "com/artifex/gsjava/util/NativePointer";
+
+ jclass bytePointerClass = g_env->FindClass(bytePointerClassName);
+ if (bytePointerClass == NULL)
+ {
+ throwNoClassDefError(g_env, bytePointerClassName);
+ return -21;
+ }
+
+ jclass nativePointerClass = g_env->FindClass(nativePointerClassName);
+ if (nativePointerClass == NULL)
+ {
+ throwNoClassDefError(g_env, nativePointerClassName);
+ return -21;
+ }
+
+ jmethodID constructor = g_env->GetMethodID(bytePointerClass, "<init>", "()V");
+ if (constructor == NULL)
+ {
+ throwNoSuchMethodError(g_env, "com.artifex.gsjava.util.BytePointer.<init>()V");
+ return -21;
+ }
+ jobject bytePointer = g_env->NewObject(bytePointerClass, constructor);
+
+ jfieldID dataPtrID = g_env->GetFieldID(nativePointerClass, "address", "J");
+ if (dataPtrID == NULL)
+ {
+ throwNoSuchFieldError(g_env, "address");
+ return -21;
+ }
+
+ jfieldID lengthID = g_env->GetFieldID(bytePointerClass, "length", "J");
+ if (lengthID == NULL)
+ {
+ throwNoSuchFieldError(g_env, "length");
+ return -21;
+ }
+
+ g_env->SetLongField(bytePointer, dataPtrID, (jlong)pimage);
+ g_env->SetLongField(bytePointer, lengthID, len);
+
+ code = callIntMethod(g_env, g_displayCallback, "onDisplaySize", DISPLAY_SIZE_SIG, (jlong)handle,
+ (jlong)device, width, height, raster, (jint)format, bytePointer);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displaySyncFunction(void *handle, void *device)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplaySync", DISPLAY_SYNC_SIG, (jlong)handle, (jlong)device);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayPageFunction(void *handle, void *device, int copies, int flush)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayPage", DISPLAY_PAGE_SIG, (jlong)handle,
+ (jlong)device, copies, flush);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayUpdateFunction(void *handle, void *device, int x, int y, int w, int h)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayUpdate", DISPLAY_UPDATE_SIG, (jlong)handle,
+ (jlong)device, x, y, w, h);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displaySeparationFunction(void *handle, void *device, int component, const char *componentName,
+ unsigned short c, unsigned short m, unsigned short y, unsigned short k)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ jsize len = strlen(componentName);
+ jbyteArray byteArray = g_env->NewByteArray(len);
+ g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)componentName);
+ code = callIntMethod(g_env, g_displayCallback, "onDisplaySeparation", DISPLAY_SEPARATION_SIG, (jlong)handle,
+ (jlong)device, component, byteArray, c, m, y, k);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayAdjustBandHeightFunction(void *handle, void *device, int bandHeight)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayAdjustBandHeght", DISPLAY_ADJUST_BAND_HEIGHT_SIG,
+ (jlong)handle, (jlong)device, bandHeight);
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
+
+int callbacks::display::displayRectangleRequestFunction(void *handle, void *device, void **memory, int *ox, int *oy,
+ int *raster, int *plane_raster, int *x, int *y, int *w, int *h)
+{
+ int code = 0;
+ if (g_env && g_displayCallback)
+ {
+ Reference memoryRef = Reference(g_env, toWrapperType(g_env, (jlong)*memory));
+ Reference oxRef = Reference(g_env, toWrapperType(g_env, (jint)*ox));
+ Reference oyRef = Reference(g_env, toWrapperType(g_env, (jint)*oy));
+ Reference rasterRef = Reference(g_env, toWrapperType(g_env, (jint)*raster));
+ Reference planeRasterRef = Reference(g_env, toWrapperType(g_env, (jint)*plane_raster));
+ Reference xRef = Reference(g_env, toWrapperType(g_env, (jint)*x));
+ Reference yRef = Reference(g_env, toWrapperType(g_env, (jint)*y));
+ Reference wRef = Reference(g_env, toWrapperType(g_env, (jint)*w));
+ Reference hRef = Reference(g_env, toWrapperType(g_env, (jint)*h));
+
+ code = callIntMethod(g_env, g_displayCallback, "onDisplayRectangleRequest", DISPLAY_RECTANGLE_REQUEST,
+ (jlong)handle, (jlong)device, memoryRef, oxRef, oyRef, rasterRef, planeRasterRef, xRef, yRef, wRef, hRef);
+
+ *memory = (void *)memoryRef.longValue();
+ *ox = oxRef.intValue();
+ *oy = oyRef.intValue();
+ *raster = rasterRef.intValue();
+ *plane_raster = planeRasterRef.intValue();
+ *x = xRef.intValue();
+ *y = yRef.intValue();
+ *w = wRef.intValue();
+ *h = hRef.intValue();
+
+ CHECK_AND_RETURN(g_env);
+ }
+ return code;
+}
diff --git a/demos/java/jni/gs_jni/callbacks.h b/demos/java/jni/gs_jni/callbacks.h
new file mode 100644
index 00000000..55508f2b
--- /dev/null
+++ b/demos/java/jni/gs_jni/callbacks.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <jni.h>
+
+namespace callbacks
+{
+ /*!
+ Sets the JNIEnv which the callbacks should use. Must be set for any Java
+ callbacks to be called.
+
+ @param env A JNIEnv.
+ */
+ void setJNIEnv(JNIEnv *env);
+
+ void setIOCallbacks(jobject stdIn, jobject stdOut, jobject stdErr);
+ int stdInFunction(void *callerHandle, char *buf, int len);
+ int stdOutFunction(void *callerHandle, const char *str, int len);
+ int stdErrFunction(void *callerHandle, const char *str, int len);
+
+ void setPollCallback(jobject poll);
+ int pollFunction(void *callerHandle);
+
+ void setDisplayCallback(jobject displayCallback);
+
+ namespace display
+ {
+ int displayOpenFunction(void *handle, void *device);
+ int displayPrecloseFunction(void *handle, void *device);
+ int displayCloseFunction(void *handle, void *device);
+ int displayPresizeFunction(void *handle, void *device, int width,
+ int height, int raster, unsigned int format);
+ int displaySizeFunction(void *handle, void *device, int width,
+ int height, int raster, unsigned int format,
+ unsigned char *pimage);
+ int displaySyncFunction(void *handle, void *device);
+ int displayPageFunction(void *handle, void *device, int copies,
+ int flush);
+ int displayUpdateFunction(void *handle, void *device, int x,
+ int y, int w, int h);
+ // display_memalloc omitted
+ // display_memfree omitted
+ int displaySeparationFunction(void *handle, void *device,
+ int component, const char *componentName, unsigned short c,
+ unsigned short m, unsigned short y, unsigned short k);
+ int displayAdjustBandHeightFunction(void *handle, void *device,
+ int bandHeight);
+ int displayRectangleRequestFunction(void *handle, void *device,
+ void **memory, int *ox, int *oy, int *raster, int *plane_raster,
+ int *x, int *y, int *w, int *h);
+ }
+
+ void setCalloutCallback(jobject calout);
+ int calloutFunction(void *instance, void *handle, const char *deviceName, int id, int size, void *data);
+} \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp
new file mode 100644
index 00000000..7858112e
--- /dev/null
+++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp
@@ -0,0 +1,555 @@
+#include "com_artifex_gsjava_GSAPI.h"
+
+#include <iapi.h>
+#include <gdevdsp.h>
+#include <string.h>
+#include <memory>
+
+#include "jni_util.h"
+#include "callbacks.h"
+
+using namespace util;
+
+static void *getAsPointer(JNIEnv *env, jobject object, gs_set_param_type type, bool *success);
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1revision
+ (JNIEnv *env, jclass, jobject revision, jint len)
+{
+ if (revision == NULL)
+ return throwNullPointerException(env, "Revision object is NULL");
+ gsapi_revision_t gsrevision;
+ jint code = gsapi_revision(&gsrevision, sizeof(gsapi_revision_t));
+ if (code == 0)
+ {
+ setByteArrayField(env, revision, "product", gsrevision.product);
+ setByteArrayField(env, revision, "copyright", gsrevision.copyright);
+ setLongField(env, revision, "revision", gsrevision.revision);
+ setLongField(env, revision, "revisionDate", gsrevision.revisiondate);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1new_1instance
+ (JNIEnv *env, jclass, jobject instance, jlong callerHandle)
+{
+ if (instance == NULL)
+ return throwNullPointerException(env, "LongReference object is NULL");
+
+ void *gsInstance;
+ int code = gsapi_new_instance(&gsInstance, (void *)callerHandle);
+ if (code == 0)
+ Reference::setValueField(env, instance, toWrapperType(env, (jlong)gsInstance));
+ return code;
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1delete_1instance
+ (JNIEnv *env, jclass, jlong instance)
+{
+ callbacks::setJNIEnv(env);
+ gsapi_delete_instance((void *)instance);
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio_1with_1handle
+ (JNIEnv *env, jclass, jlong instance, jobject stdIn, jobject stdOut, jobject stdErr, jlong callerHandle)
+{
+ int code = gsapi_set_stdio_with_handle((void *)instance, callbacks::stdInFunction,
+ callbacks::stdOutFunction, callbacks::stdErrFunction, (void *)callerHandle);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setIOCallbacks(stdIn, stdOut, stdErr);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio
+ (JNIEnv *env, jclass, jlong instance, jobject stdIn, jobject stdOut, jobject stdErr)
+{
+ int code = gsapi_set_stdio((void *)instance, callbacks::stdInFunction,
+ callbacks::stdOutFunction, callbacks::stdErrFunction);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setIOCallbacks(stdIn, stdOut, stdErr);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll_1with_1handle
+ (JNIEnv *env, jclass, jlong instance, jobject poll, jlong callerHandle)
+{
+ int code = gsapi_set_poll_with_handle((void *)instance, callbacks::pollFunction, (void *)callerHandle);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setPollCallback(poll);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll
+ (JNIEnv *env, jclass, jlong instance, jobject poll)
+{
+ int code = gsapi_set_poll((void *)instance, callbacks::pollFunction);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setPollCallback(poll);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callback
+ (JNIEnv *env, jclass, jlong instance, jobject displayCallback)
+{
+ display_callback *cb = new display_callback;
+ cb->size = sizeof(display_callback);
+ cb->version_major = DISPLAY_VERSION_MAJOR;
+ cb->version_minor = DISPLAY_VERSION_MINOR;
+
+ cb->display_open = callbacks::display::displayOpenFunction;
+ cb->display_preclose = callbacks::display::displayPrecloseFunction;
+ cb->display_close = callbacks::display::displayCloseFunction;
+ cb->display_presize = callbacks::display::displayPresizeFunction;
+ cb->display_size = callbacks::display::displaySizeFunction;
+ cb->display_sync = callbacks::display::displaySyncFunction;
+ cb->display_page = callbacks::display::displayPageFunction;
+ cb->display_update = callbacks::display::displayUpdateFunction;
+ cb->display_memalloc = NULL;
+ cb->display_memfree = NULL;
+ cb->display_separation = callbacks::display::displaySeparationFunction;
+ cb->display_adjust_band_height = callbacks::display::displayAdjustBandHeightFunction;
+ cb->display_rectangle_request = callbacks::display::displayRectangleRequestFunction;
+
+ int code = gsapi_set_display_callback((void *)instance, cb);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setDisplayCallback(displayCallback);
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1register_1callout
+ (JNIEnv *env, jclass, jlong instance, jobject callout, jlong calloutHandle)
+{
+ int code = gsapi_register_callout((void *)instance, callbacks::calloutFunction, (void *)calloutHandle);
+ if (code == 0)
+ {
+ callbacks::setJNIEnv(env);
+ callbacks::setCalloutCallback(callout);
+ }
+ return code;
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1deregister_1callout
+ (JNIEnv *env, jclass, jlong instance, jobject callout, jlong calloutHandle)
+{
+ gsapi_deregister_callout((void *)instance, callbacks::calloutFunction, (void *)calloutHandle);
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1arg_1encoding
+ (JNIEnv *env, jclass, jlong instance, jint encoding)
+{
+ return gsapi_set_arg_encoding((void *)instance, encoding);
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1default_1device_1list
+ (JNIEnv *env, jclass, jlong instance, jbyteArray list, jint listlen)
+{
+ if (list == NULL)
+ return throwNullPointerException(env, "list");
+ jboolean isCopy = false;
+ callbacks::setJNIEnv(env);
+ int code = gsapi_set_default_device_list((void *)instance,
+ (const char *)env->GetByteArrayElements(list, &isCopy), listlen);
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1default_1device_1list
+ (JNIEnv *env, jclass, jlong instance, jobject list, jobject listlen)
+{
+ char *clist = NULL;
+ int clistlen = 0;
+ int code = gsapi_get_default_device_list((void *)instance, &clist, &clistlen);
+ if (code == 0)
+ {
+ if (list)
+ {
+ jbyteArray arr = env->NewByteArray(clistlen);
+ env->SetByteArrayRegion(arr, 0, clistlen, (jbyte *)clist);
+ Reference::setValueField(env, list, arr);
+ env->DeleteLocalRef(arr);
+ }
+ if (listlen)
+ Reference::setValueField(env, listlen, toWrapperType(env, (jint)clistlen));
+ }
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args
+ (JNIEnv *env, jclass, jlong instance, jint argc, jobjectArray argv)
+{
+ if (argv == NULL)
+ return throwNullPointerException(env, "argv");
+ char **cargv = jbyteArray2DToCharArray(env, argv);
+ callbacks::setJNIEnv(env);
+ int code = gsapi_init_with_args((void *)instance, argc, cargv);
+ delete2DByteArray(argc, cargv);
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin
+ (JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode)
+{
+ int exitCode;
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_string_begin((void *)instance, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1continue
+ (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint length, jint userErrors, jobject pExitCode)
+{
+ if (str == NULL)
+ return throwNullPointerException(env, "str");
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_string_continue((void *)instance, cstring, length, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1end
+ (JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode)
+{
+ int exitCode;
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_string_end((void *)instance, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1with_1length
+ (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint length, jint userErrors, jobject pExitCode)
+{
+ if (str == NULL)
+ return throwNullPointerException(env, "str");
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_string_with_length((void *)instance, cstring, length, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string
+ (JNIEnv *env, jclass, jlong instance, jbyteArray str, jint userErrors, jobject pExitCode)
+{
+ if (str == NULL)
+ return throwNullPointerException(env, "str");
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_string((void *)instance, cstring, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1file
+ (JNIEnv *env, jclass, jlong instance, jbyteArray fileName, jint userErrors, jobject pExitCode)
+{
+ if (fileName == NULL)
+ return throwNullPointerException(env, "fileName");
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(fileName, &copy);
+ callbacks::setJNIEnv(env);
+ int code = gsapi_run_file((void *)instance, cstring, userErrors, &exitCode);
+ if (pExitCode)
+ Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1exit
+ (JNIEnv *env, jclass, jlong instance)
+{
+ return gsapi_exit((void *)instance);
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1param
+ (JNIEnv *env, jclass, jlong instance, jbyteArray param, jobject value, jint paramType)
+{
+ if (!param)
+ {
+ throwNullPointerException(env, "param");
+ return -1;
+ }
+
+ gs_set_param_type type = (gs_set_param_type)paramType;
+ bool paramSuccess;
+ void *data = getAsPointer(env, value, type, &paramSuccess);
+ if (!paramSuccess)
+ {
+ throwIllegalArgumentException(env, "paramType");
+ return -1;
+ }
+
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(param, &copy);
+
+ callbacks::setJNIEnv(env);
+ int code = gsapi_set_param((void *)instance, cstring, data, type);
+ free(data);
+
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1param
+ (JNIEnv *env, jclass, jlong instance, jbyteArray param, jlong value, jint paramType)
+{
+ if (!param)
+ {
+ throwNullPointerException(env, "paramType");
+ return -1;
+ }
+
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(param, &copy);
+
+ int ret = gsapi_get_param((void *)instance, cstring, (void *)value, (gs_set_param_type)paramType);
+
+ return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1param_1once
+ (JNIEnv *env, jclass, jlong instance, jbyteArray param, jobject value, jint paramType)
+{
+ jboolean copy = false;
+ int exitCode;
+ const char *cstring = (const char *)env->GetByteArrayElements(param, &copy);
+
+ int bytes = gsapi_get_param((void *)instance, cstring, NULL, (gs_set_param_type)paramType);
+ if (bytes < 0)
+ return bytes;
+
+ void *data = new char[bytes];
+ int code = gsapi_get_param((void *)instance, cstring, data, (gs_set_param_type)paramType);
+ if (code < 0)
+ {
+ delete[] data;
+ return code;
+ }
+
+ int stripped = paramType & ~(gs_spt_more_to_come);
+ Reference ref = Reference(env, value);
+
+ jbyteArray arr = NULL;
+ const char *str = NULL;
+ int len = 0;
+ switch (stripped)
+ {
+ case gs_spt_null:
+ break;
+ case gs_spt_bool:
+ ref.set((jboolean)*((int *)data));
+ break;
+ case gs_spt_int:
+ ref.set(*((jint *)data));
+ break;
+ case gs_spt_float:
+ ref.set(*((jfloat *)data));
+ break;
+ case gs_spt_long:
+ ref.set(*((jlong *)data));
+ break;
+ case gs_spt_i64:
+ ref.set((jlong)*((long long *)data));
+ break;
+ case gs_spt_size_t:
+ ref.set((jlong)*((size_t *)data));
+ break;
+ case gs_spt_name:
+ case gs_spt_string:
+ case gs_spt_parsed:
+ str = (const char *)data;
+ len = strlen(str) + 1;
+ arr = env->NewByteArray(len);
+ env->SetByteArrayRegion(arr, 0, len, (const jbyte *)str);
+ ref.set(arr);
+ break;
+ case gs_spt_invalid:
+ default:
+ throwIllegalArgumentException(env, "paramType");
+ delete[] data;
+ return -1;
+ break;
+ }
+ delete[] data;
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1enumerate_1params
+ (JNIEnv *env, jclass, jlong instance, jobject iter, jobject key, jobject paramType)
+{
+ if (!iter)
+ {
+ throwNullPointerException(env, "iterator is NULL");
+ return -1;
+ }
+
+ Reference iterRef = Reference(env, iter);
+
+ Reference keyRef = Reference(env, key);
+ Reference typeRef = Reference(env, paramType);
+
+ void *citer = (void *)iterRef.longValue();
+
+ if (env->ExceptionCheck())
+ return -1;
+
+ const char *ckey;
+ gs_set_param_type type;
+
+ int code = gsapi_enumerate_params((void *)instance, &citer, &ckey, &type);
+
+ if (code == 0)
+ {
+ iterRef.set((jlong)citer);
+
+ jsize len = strlen(ckey) + 1;
+ jbyteArray arr = env->NewByteArray(len);
+ env->SetByteArrayRegion(arr, 0, len, (const jbyte *)ckey);
+ keyRef.set(arr);
+ env->DeleteLocalRef(arr);
+
+ typeRef.set((jint)type);
+ }
+
+ return code;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1add_1control_1path
+ (JNIEnv *env, jclass, jlong instance, jint type, jbyteArray path)
+{
+ if (!path)
+ {
+ throwNullPointerException(env, "path is NULL");
+ return -1;
+ }
+
+ jboolean copy = false;
+ const char *cstring = (const char *)env->GetByteArrayElements(path, &copy);
+
+ int exitCode = gsapi_add_control_path((void *)instance, type, cstring);
+
+ return exitCode;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1remove_1control_1path
+(JNIEnv *env, jclass, jlong instance, jint type, jbyteArray path)
+{
+ if (!path)
+ {
+ throwNullPointerException(env, "path is NULL");
+ return -1;
+ }
+
+ jboolean copy = false;
+ const char *cstring = (const char *)env->GetByteArrayElements(path, &copy);
+
+ int exitCode = gsapi_remove_control_path((void *)instance, type, cstring);
+
+ return exitCode;
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1purge_1control_1paths
+ (JNIEnv *, jclass, jlong instance, jint type)
+{
+ gsapi_purge_control_paths((void *)instance, type);
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1activate_1path_1control
+ (JNIEnv *, jclass, jlong instance, jboolean enable)
+{
+ gsapi_activate_path_control((void *)instance, enable);
+}
+
+JNIEXPORT jboolean JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1is_1path_1control_1active
+ (JNIEnv *env, jclass, jlong instance)
+{
+ return gsapi_is_path_control_active((void *)instance);
+}
+
+void *getAsPointer(JNIEnv *env, jobject object, gs_set_param_type type, bool *success)
+{
+ *success = true;
+ void *result = NULL;
+ int stripped = type & ~gs_spt_more_to_come;
+
+ jbyteArray arr = NULL;
+ jboolean copy = false;
+ const char *cstring = NULL;
+ jsize len = 0;
+ switch (stripped)
+ {
+ case gs_spt_null:
+ return result;
+ break;
+ case gs_spt_bool:
+ result = malloc(sizeof(int));
+ *((int *)result) = (bool)toBoolean(env, object);
+ break;
+ case gs_spt_int:
+ result = malloc(sizeof(int));
+ *((int *)result) = (int)toInt(env, object);
+ break;
+ case gs_spt_float:
+ result = malloc(sizeof(float));
+ *((float *)result) = (float)toFloat(env, object);
+ break;
+ case gs_spt_long:
+ case gs_spt_i64:
+ result = malloc(sizeof(long long));
+ *((long long *)result) = (long long)toLong(env, object);
+ break;
+ case gs_spt_size_t:
+ result = malloc(sizeof(size_t));
+ *((size_t *)result) = (size_t)toLong(env, object);
+ break;
+ case gs_spt_name:
+ case gs_spt_string:
+ case gs_spt_parsed:
+ arr = (jbyteArray)object;
+ cstring = (const char *)env->GetByteArrayElements(arr, &copy);
+ len = env->GetArrayLength(arr);
+ result = malloc(sizeof(char) * len);
+ //((char *)result)[len - 1] = 0;
+ memcpy(result, cstring, len);
+ break;
+ case gs_spt_invalid:
+ default:
+ *success = false;
+ break;
+ }
+ if (env->ExceptionCheck())
+ {
+ if (result)
+ free(result);
+ result = NULL;
+ *success = false;
+ }
+ return result;
+}
diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h
new file mode 100644
index 00000000..68c61e58
--- /dev/null
+++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.h
@@ -0,0 +1,386 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_artifex_gsjava_GSAPI */
+
+#ifndef _Included_com_artifex_gsjava_GSAPI
+#define _Included_com_artifex_gsjava_GSAPI
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_artifex_gsjava_GSAPI_GS_NULL
+#define com_artifex_gsjava_GSAPI_GS_NULL 0i64
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_OK
+#define com_artifex_gsjava_GSAPI_GS_ERROR_OK 0L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNKNOWNERROR
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNKNOWNERROR -1L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_DICTFULL
+#define com_artifex_gsjava_GSAPI_GS_ERROR_DICTFULL -2L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_DICTSTACKOVERFLOW
+#define com_artifex_gsjava_GSAPI_GS_ERROR_DICTSTACKOVERFLOW -3L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_DICTSTACKUNDERFLOW
+#define com_artifex_gsjava_GSAPI_GS_ERROR_DICTSTACKUNDERFLOW -4L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_EXECSTACKOVERFLOW
+#define com_artifex_gsjava_GSAPI_GS_ERROR_EXECSTACKOVERFLOW -5L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INTERRUPT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INTERRUPT -6L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDACCESS
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDACCESS -7L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDEXIT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDEXIT -8L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDFILEACCESS
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDFILEACCESS -9L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDFONT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDFONT -10L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDRESTORE
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDRESTORE -11L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_IOERROR
+#define com_artifex_gsjava_GSAPI_GS_ERROR_IOERROR -12L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_LIMITCHECK
+#define com_artifex_gsjava_GSAPI_GS_ERROR_LIMITCHECK -13L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_NOCURRENTPOINT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_NOCURRENTPOINT -14L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_RANGECHECK
+#define com_artifex_gsjava_GSAPI_GS_ERROR_RANGECHECK -15L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_STACKOVERFLOW
+#define com_artifex_gsjava_GSAPI_GS_ERROR_STACKOVERFLOW -16L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_STACKUNDERFLOW
+#define com_artifex_gsjava_GSAPI_GS_ERROR_STACKUNDERFLOW -17L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_SYNTAXERROR
+#define com_artifex_gsjava_GSAPI_GS_ERROR_SYNTAXERROR -18L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_TIMEOUT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_TIMEOUT -19L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_TYPECHECK
+#define com_artifex_gsjava_GSAPI_GS_ERROR_TYPECHECK -20L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINED
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINED -21L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDFILENAME
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDFILENAME -22L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDRESULT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDRESULT -23L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNMATCHEDMARK
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNMATCHEDMARK -24L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_VMERROR
+#define com_artifex_gsjava_GSAPI_GS_ERROR_VMERROR -25L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_CONFIGURATION_ERROR
+#define com_artifex_gsjava_GSAPI_GS_ERROR_CONFIGURATION_ERROR -26L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDRESOURCE
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINEDRESOURCE -27L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_UNREGISTERED
+#define com_artifex_gsjava_GSAPI_GS_ERROR_UNREGISTERED -28L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDCONTEXT
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALIDCONTEXT -29L
+#undef com_artifex_gsjava_GSAPI_GS_ERROR_INVALID
+#define com_artifex_gsjava_GSAPI_GS_ERROR_INVALID -30L
+#undef com_artifex_gsjava_GSAPI_GS_COLORS_NATIVE
+#define com_artifex_gsjava_GSAPI_GS_COLORS_NATIVE 1L
+#undef com_artifex_gsjava_GSAPI_GS_COLORS_GRAY
+#define com_artifex_gsjava_GSAPI_GS_COLORS_GRAY 2L
+#undef com_artifex_gsjava_GSAPI_GS_COLORS_RGB
+#define com_artifex_gsjava_GSAPI_GS_COLORS_RGB 4L
+#undef com_artifex_gsjava_GSAPI_GS_COLORS_CMYK
+#define com_artifex_gsjava_GSAPI_GS_COLORS_CMYK 8L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_COLORS_SEPARATION
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_COLORS_SEPARATION 524288L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_COLORS_MASK
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_COLORS_MASK 524303i64
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_NONE
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_NONE 0L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_FIRST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_FIRST 16L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_LAST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_LAST 32L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_UNUSED_FIRST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_UNUSED_FIRST 64L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_UNUSED_LAST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_UNUSED_LAST 128L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_MASK
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_ALPHA_MASK 240i64
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_1
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_1 256L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_2
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_2 512L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_4
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_4 1024L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_8
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_8 2048L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_12
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_12 4096L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_16
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_16 8L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_MASK
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_DEPTH_MASK 65280i64
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_BIGENDIAN
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_BIGENDIAN 0L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_LITTLEENDIAN
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_LITTLEENDIAN 65536L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_ENDIAN_MASK
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_ENDIAN_MASK 65536i64
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_TOPFIRST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_TOPFIRST 0L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_BOTTOMFIRST
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_BOTTOMFIRST 131072L
+#undef com_artifex_gsjava_GSAPI_GS_DISPLAY_FIRSTROW_MASK
+#define com_artifex_gsjava_GSAPI_GS_DISPLAY_FIRSTROW_MASK 131072i64
+#undef com_artifex_gsjava_GSAPI_GS_SPT_INVALID
+#define com_artifex_gsjava_GSAPI_GS_SPT_INVALID -1L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_NULL
+#define com_artifex_gsjava_GSAPI_GS_SPT_NULL 0L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_BOOL
+#define com_artifex_gsjava_GSAPI_GS_SPT_BOOL 1L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_INT
+#define com_artifex_gsjava_GSAPI_GS_SPT_INT 2L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_FLOAT
+#define com_artifex_gsjava_GSAPI_GS_SPT_FLOAT 3L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_NAME
+#define com_artifex_gsjava_GSAPI_GS_SPT_NAME 4L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_STRING
+#define com_artifex_gsjava_GSAPI_GS_SPT_STRING 5L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_LONG
+#define com_artifex_gsjava_GSAPI_GS_SPT_LONG 6L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_I64
+#define com_artifex_gsjava_GSAPI_GS_SPT_I64 7L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_SIZE_T
+#define com_artifex_gsjava_GSAPI_GS_SPT_SIZE_T 8L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_PARSED
+#define com_artifex_gsjava_GSAPI_GS_SPT_PARSED 9L
+#undef com_artifex_gsjava_GSAPI_GS_SPT_MORE_TO_COME
+#define com_artifex_gsjava_GSAPI_GS_SPT_MORE_TO_COME -2147483648L
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_revision
+ * Signature: (Lcom/artifex/gsjava/GSAPI/Revision;I)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1revision
+ (JNIEnv *, jclass, jobject, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_new_instance
+ * Signature: (Lcom/artifex/gsjava/util/Reference;J)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1new_1instance
+ (JNIEnv *, jclass, jobject, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_delete_instance
+ * Signature: (J)V
+ */
+ JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1delete_1instance
+ (JNIEnv *, jclass, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_stdio_with_handle
+ * Signature: (JLcom/artifex/gsjava/callbacks/IStdInFunction;Lcom/artifex/gsjava/callbacks/IStdOutFunction;Lcom/artifex/gsjava/callbacks/IStdErrFunction;J)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio_1with_1handle
+ (JNIEnv *, jclass, jlong, jobject, jobject, jobject, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_stdio
+ * Signature: (JLcom/artifex/gsjava/callbacks/IStdInFunction;Lcom/artifex/gsjava/callbacks/IStdOutFunction;Lcom/artifex/gsjava/callbacks/IStdErrFunction;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio
+ (JNIEnv *, jclass, jlong, jobject, jobject, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_poll_with_handle
+ * Signature: (JLcom/artifex/gsjava/callbacks/IPollFunction;J)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll_1with_1handle
+ (JNIEnv *, jclass, jlong, jobject, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_poll
+ * Signature: (JLcom/artifex/gsjava/callbacks/IPollFunction;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1poll
+ (JNIEnv *, jclass, jlong, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_display_callback
+ * Signature: (JLcom/artifex/gsjava/callbacks/DisplayCallback;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callback
+ (JNIEnv *, jclass, jlong, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_register_callout
+ * Signature: (JLcom/artifex/gsjava/callbacks/ICalloutFunction;J)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1register_1callout
+ (JNIEnv *, jclass, jlong, jobject, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_deregister_callout
+ * Signature: (JLcom/artifex/gsjava/callbacks/ICalloutFunction;J)V
+ */
+ JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1deregister_1callout
+ (JNIEnv *, jclass, jlong, jobject, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_arg_encoding
+ * Signature: (JI)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1arg_1encoding
+ (JNIEnv *, jclass, jlong, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_default_device_list
+ * Signature: (J[BI)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1default_1device_1list
+ (JNIEnv *, jclass, jlong, jbyteArray, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_get_default_device_list
+ * Signature: (JLcom/artifex/gsjava/util/Reference;Lcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1default_1device_1list
+ (JNIEnv *, jclass, jlong, jobject, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_init_with_args
+ * Signature: (JI[[B)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args
+ (JNIEnv *, jclass, jlong, jint, jobjectArray);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_string_begin
+ * Signature: (JILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin
+ (JNIEnv *, jclass, jlong, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_string_continue
+ * Signature: (J[BIILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1continue
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_string_end
+ * Signature: (JILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1end
+ (JNIEnv *, jclass, jlong, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_string_with_length
+ * Signature: (J[BIILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1with_1length
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_string
+ * Signature: (J[BILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_run_file
+ * Signature: (J[BILcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1file
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_exit
+ * Signature: (J)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1exit
+ (JNIEnv *, jclass, jlong);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_set_param
+ * Signature: (J[BLjava/lang/Object;I)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1param
+ (JNIEnv *, jclass, jlong, jbyteArray, jobject, jint);
+
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1param
+ (JNIEnv *, jclass, jlong, jbyteArray, jlong, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_get_param_once
+ * Signature: (J[BLcom/artifex/gsjava/util/Reference;I)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1get_1param_1once
+ (JNIEnv *, jclass, jlong, jbyteArray, jobject, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_enumerate_params
+ * Signature: (JLcom/artifex/gsjava/util/Reference;Lcom/artifex/gsjava/util/ByteArrayReference;Lcom/artifex/gsjava/util/Reference;)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1enumerate_1params
+ (JNIEnv *, jclass, jlong, jobject, jobject, jobject);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_add_control_path
+ * Signature: (JI[B)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1add_1control_1path
+ (JNIEnv *, jclass, jlong, jint, jbyteArray);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_remove_control_path
+ * Signature: (JI[B)I
+ */
+ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1remove_1control_1path
+ (JNIEnv *, jclass, jlong, jint, jbyteArray);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_purge_control_paths
+ * Signature: (JI)V
+ */
+ JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1purge_1control_1paths
+ (JNIEnv *, jclass, jlong, jint);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_activate_path_control
+ * Signature: (JZ)V
+ */
+ JNIEXPORT void JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1activate_1path_1control
+ (JNIEnv *, jclass, jlong, jboolean);
+
+ /*
+ * Class: com_artifex_gsjava_GSAPI
+ * Method: gsapi_is_path_control_active
+ * Signature: (J)Z
+ */
+ JNIEXPORT jboolean JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1is_1path_1control_1active
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.cpp b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.cpp
new file mode 100644
index 00000000..b58c070c
--- /dev/null
+++ b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.cpp
@@ -0,0 +1,131 @@
+#include "com_artifex_gsjava_util_NativePointer.h"
+
+#include <memory>
+
+#include "jni_util.h"
+
+using namespace util;
+
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_mallocNative
+(JNIEnv *env, jclass, jlong size)
+{
+ void *ptr = malloc((size_t)size);
+ if (ptr == NULL)
+ return throwAllocationError(env, "malloc");
+ return (jlong)ptr;
+}
+
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_callocNative
+(JNIEnv *env, jclass, jlong count, jlong size)
+{
+ void *ptr = calloc(count, (size_t)size);
+ if (ptr == NULL)
+ return throwAllocationError(env, "calloc");
+ return (jlong)ptr;
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_freeNative
+(JNIEnv *, jclass, jlong block)
+{
+ free((void *)block);
+}
+
+JNIEXPORT jbyteArray JNICALL Java_com_artifex_gsjava_util_NativePointer_byteArrayNative
+(JNIEnv *env, jclass, jlong address, jlong len)
+{
+ jbyteArray array = env->NewByteArray(len);
+ env->SetByteArrayRegion(array, 0, len, (const jbyte *)address);
+ return array;
+}
+
+JNIEXPORT jbyte JNICALL Java_com_artifex_gsjava_util_NativePointer_byteAtNative
+(JNIEnv *, jclass, jlong address, jlong index)
+{
+ return ((jbyte *)address)[index];
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setByteNative
+(JNIEnv *, jclass, jlong address, jlong index, jbyte value)
+{
+ ((jbyte *)address)[index];
+}
+
+JNIEXPORT jcharArray JNICALL Java_com_artifex_gsjava_util_NativePointer_charArrayNative
+(JNIEnv *env, jclass, jlong address, jlong len)
+{
+ jcharArray array = env->NewCharArray(len);
+ env->SetCharArrayRegion(array, 0, len, (const jchar *)address);
+ return array;
+}
+
+JNIEXPORT jchar JNICALL Java_com_artifex_gsjava_util_NativePointer_charAtNative
+(JNIEnv *, jclass, jlong address, jlong index)
+{
+ return ((jchar *)address)[index];
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setCharNative
+(JNIEnv *, jclass, jlong address, jlong index, jchar value)
+{
+ ((jchar *)address)[index] = value;
+}
+
+JNIEXPORT jshortArray JNICALL Java_com_artifex_gsjava_util_NativePointer_shortArrayNative
+(JNIEnv *env, jclass, jlong address, jlong len)
+{
+ jshortArray array = env->NewShortArray(len);
+ env->SetShortArrayRegion(array, 0, len, (const jshort *)address);
+ return array;
+}
+
+JNIEXPORT jshort JNICALL Java_com_artifex_gsjava_util_NativePointer_shortAtNative
+(JNIEnv *, jclass, jlong address, jlong index)
+{
+ return ((jshort *)address)[index];
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setShortNative
+(JNIEnv *, jclass, jlong address, jlong index, jshort value)
+{
+ ((jshort *)address)[index] = value;
+}
+
+JNIEXPORT jintArray JNICALL Java_com_artifex_gsjava_util_NativePointer_intArrayNative
+(JNIEnv *env, jclass, jlong address, jlong len)
+{
+ jintArray array = env->NewIntArray(len);
+ env->SetIntArrayRegion(array, 0, len, (const jint *)address);
+ return array;
+}
+
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_util_NativePointer_intAtNative
+(JNIEnv *, jclass, jlong address, jlong index)
+{
+ return ((jint *)address)[index];
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setIntNative
+(JNIEnv *, jclass, jlong address, jlong index, jint value)
+{
+ ((jint *)address)[index] = value;
+}
+
+JNIEXPORT jlongArray JNICALL Java_com_artifex_gsjava_util_NativePointer_longArrayNative
+(JNIEnv *env, jclass, jlong address, jlong len)
+{
+ jlongArray array = env->NewLongArray(len);
+ env->SetLongArrayRegion(array, 0, len, (const jlong *)address);
+ return array;
+}
+
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_longAtNative
+(JNIEnv *, jclass, jlong address, jlong index)
+{
+ return ((jlong *)address)[index];
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setLongNative
+(JNIEnv *, jclass, jlong address, jlong index, jlong value)
+{
+ ((jlong *)address)[index] = value;
+} \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h
new file mode 100644
index 00000000..8dd6a30b
--- /dev/null
+++ b/demos/java/jni/gs_jni/com_artifex_gsjava_util_NativePointer.h
@@ -0,0 +1,169 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_artifex_gsjava_util_NativePointer */
+
+#ifndef _Included_com_artifex_gsjava_util_NativePointer
+#define _Included_com_artifex_gsjava_util_NativePointer
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_artifex_gsjava_util_NativePointer_NULL
+#define com_artifex_gsjava_util_NativePointer_NULL 0i64
+#undef com_artifex_gsjava_util_NativePointer_BYTE_SIZE
+#define com_artifex_gsjava_util_NativePointer_BYTE_SIZE 1i64
+#undef com_artifex_gsjava_util_NativePointer_CHAR_SIZE
+#define com_artifex_gsjava_util_NativePointer_CHAR_SIZE 2i64
+#undef com_artifex_gsjava_util_NativePointer_SHORT_SIZE
+#define com_artifex_gsjava_util_NativePointer_SHORT_SIZE 2i64
+#undef com_artifex_gsjava_util_NativePointer_INT_SIZE
+#define com_artifex_gsjava_util_NativePointer_INT_SIZE 4i64
+#undef com_artifex_gsjava_util_NativePointer_LONG_SIZE
+#define com_artifex_gsjava_util_NativePointer_LONG_SIZE 8i64
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: mallocNative
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_mallocNative
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: callocNative
+ * Signature: (JJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_callocNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: freeNative
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_freeNative
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: byteArrayNative
+ * Signature: (JJ)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_artifex_gsjava_util_NativePointer_byteArrayNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: byteAtNative
+ * Signature: (JJ)B
+ */
+JNIEXPORT jbyte JNICALL Java_com_artifex_gsjava_util_NativePointer_byteAtNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: setByteNative
+ * Signature: (JJB)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setByteNative
+ (JNIEnv *, jclass, jlong, jlong, jbyte);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: charArrayNative
+ * Signature: (JJ)[C
+ */
+JNIEXPORT jcharArray JNICALL Java_com_artifex_gsjava_util_NativePointer_charArrayNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: charAtNative
+ * Signature: (JJ)C
+ */
+JNIEXPORT jchar JNICALL Java_com_artifex_gsjava_util_NativePointer_charAtNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: setCharNative
+ * Signature: (JJC)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setCharNative
+ (JNIEnv *, jclass, jlong, jlong, jchar);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: shortArrayNative
+ * Signature: (JJ)[S
+ */
+JNIEXPORT jshortArray JNICALL Java_com_artifex_gsjava_util_NativePointer_shortArrayNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: shortAtNative
+ * Signature: (JJ)S
+ */
+JNIEXPORT jshort JNICALL Java_com_artifex_gsjava_util_NativePointer_shortAtNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: setShortNative
+ * Signature: (JJS)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setShortNative
+ (JNIEnv *, jclass, jlong, jlong, jshort);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: intArrayNative
+ * Signature: (JJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_com_artifex_gsjava_util_NativePointer_intArrayNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: intAtNative
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_artifex_gsjava_util_NativePointer_intAtNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: setIntNative
+ * Signature: (JJI)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setIntNative
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: longArrayNative
+ * Signature: (JJ)[J
+ */
+JNIEXPORT jlongArray JNICALL Java_com_artifex_gsjava_util_NativePointer_longArrayNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: longAtNative
+ * Signature: (JJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_artifex_gsjava_util_NativePointer_longAtNative
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_artifex_gsjava_util_NativePointer
+ * Method: setLongNative
+ * Signature: (JJJ)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_gsjava_util_NativePointer_setLongNative
+ (JNIEnv *, jclass, jlong, jlong, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/demos/java/jni/gs_jni/dllmain.cpp b/demos/java/jni/gs_jni/dllmain.cpp
new file mode 100644
index 00000000..f6091f3f
--- /dev/null
+++ b/demos/java/jni/gs_jni/dllmain.cpp
@@ -0,0 +1,19 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+
+#include <Windows.h>
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+} \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/framework.h b/demos/java/jni/gs_jni/framework.h
new file mode 100644
index 00000000..54b83e94
--- /dev/null
+++ b/demos/java/jni/gs_jni/framework.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files
+#include <windows.h>
diff --git a/demos/java/jni/gs_jni/gs_jni.sln b/demos/java/jni/gs_jni/gs_jni.sln
new file mode 100644
index 00000000..965b2df5
--- /dev/null
+++ b/demos/java/jni/gs_jni/gs_jni.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30225.117
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gs_jni", "gs_jni.vcxproj", "{72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Debug|x64.ActiveCfg = Debug|x64
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Debug|x64.Build.0 = Debug|x64
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Debug|x86.ActiveCfg = Debug|Win32
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Debug|x86.Build.0 = Debug|Win32
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Release|x64.ActiveCfg = Release|x64
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Release|x64.Build.0 = Release|x64
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Release|x86.ActiveCfg = Release|Win32
+ {72CAF1B0-7CA6-4044-8705-E0FB2DFF01DD}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {70A01221-9F8F-496E-A834-AA2EB06F515A}
+ EndGlobalSection
+EndGlobal
diff --git a/demos/java/jni/gs_jni/gs_jni.vcxproj b/demos/java/jni/gs_jni/gs_jni.vcxproj
new file mode 100644
index 00000000..eae045e8
--- /dev/null
+++ b/demos/java/jni/gs_jni/gs_jni.vcxproj
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectGuid>{72caf1b0-7ca6-4044-8705-e0fb2dff01dd}</ProjectGuid>
+ <RootNamespace>gsjni</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;GSJNI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\..\psi;$(SolutionDir)include;$(SolutionDir)..\..\..\..\..\ghostpdl\devices;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\..\debugbin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;GSJNI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\..\psi;$(SolutionDir)include;$(SolutionDir)..\..\..\..\..\ghostpdl\devices;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;GSJNI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\..\psi;$(SolutionDir)include;$(SolutionDir)..\..\..\..\..\ghostpdl\devices;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ <AdditionalDependencies>gpdldll64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\..\debugbin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;GSJNI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\..\psi;$(SolutionDir)include;$(SolutionDir)..\..\..\..\..\ghostpdl\devices;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\..\bin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>gpdldll64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="callbacks.h" />
+ <ClInclude Include="com_artifex_gsjava_GSAPI.h" />
+ <ClInclude Include="com_artifex_gsjava_util_NativePointer.h" />
+ <ClInclude Include="framework.h" />
+ <ClInclude Include="jni_util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="callbacks.cpp" />
+ <ClCompile Include="com_artifex_gsjava_GSAPI.cpp" />
+ <ClCompile Include="com_artifex_gsjava_util_NativePointer.cpp" />
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="jni_util.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/gs_jni.vcxproj.filters b/demos/java/jni/gs_jni/gs_jni.vcxproj.filters
new file mode 100644
index 00000000..14063f1b
--- /dev/null
+++ b/demos/java/jni/gs_jni/gs_jni.vcxproj.filters
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="framework.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="com_artifex_gsjava_GSAPI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="jni_util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="callbacks.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="com_artifex_gsjava_util_NativePointer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="com_artifex_gsjava_GSAPI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="jni_util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="callbacks.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="com_artifex_gsjava_util_NativePointer.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/include/classfile_constants.h b/demos/java/jni/gs_jni/include/classfile_constants.h
new file mode 100644
index 00000000..e5c20cd9
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/classfile_constants.h
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef CLASSFILE_CONSTANTS_H
+#define CLASSFILE_CONSTANTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Classfile version number for this information */
+#define JVM_CLASSFILE_MAJOR_VERSION 52
+#define JVM_CLASSFILE_MINOR_VERSION 0
+
+/* Flags */
+
+enum {
+ JVM_ACC_PUBLIC = 0x0001,
+ JVM_ACC_PRIVATE = 0x0002,
+ JVM_ACC_PROTECTED = 0x0004,
+ JVM_ACC_STATIC = 0x0008,
+ JVM_ACC_FINAL = 0x0010,
+ JVM_ACC_SYNCHRONIZED = 0x0020,
+ JVM_ACC_SUPER = 0x0020,
+ JVM_ACC_VOLATILE = 0x0040,
+ JVM_ACC_BRIDGE = 0x0040,
+ JVM_ACC_TRANSIENT = 0x0080,
+ JVM_ACC_VARARGS = 0x0080,
+ JVM_ACC_NATIVE = 0x0100,
+ JVM_ACC_INTERFACE = 0x0200,
+ JVM_ACC_ABSTRACT = 0x0400,
+ JVM_ACC_STRICT = 0x0800,
+ JVM_ACC_SYNTHETIC = 0x1000,
+ JVM_ACC_ANNOTATION = 0x2000,
+ JVM_ACC_ENUM = 0x4000
+};
+
+/* Used in newarray instruction. */
+
+enum {
+ JVM_T_BOOLEAN = 4,
+ JVM_T_CHAR = 5,
+ JVM_T_FLOAT = 6,
+ JVM_T_DOUBLE = 7,
+ JVM_T_BYTE = 8,
+ JVM_T_SHORT = 9,
+ JVM_T_INT = 10,
+ JVM_T_LONG = 11
+};
+
+/* Constant Pool Entries */
+
+enum {
+ JVM_CONSTANT_Utf8 = 1,
+ JVM_CONSTANT_Unicode = 2, /* unused */
+ JVM_CONSTANT_Integer = 3,
+ JVM_CONSTANT_Float = 4,
+ JVM_CONSTANT_Long = 5,
+ JVM_CONSTANT_Double = 6,
+ JVM_CONSTANT_Class = 7,
+ JVM_CONSTANT_String = 8,
+ JVM_CONSTANT_Fieldref = 9,
+ JVM_CONSTANT_Methodref = 10,
+ JVM_CONSTANT_InterfaceMethodref = 11,
+ JVM_CONSTANT_NameAndType = 12,
+ JVM_CONSTANT_MethodHandle = 15, // JSR 292
+ JVM_CONSTANT_MethodType = 16, // JSR 292
+ JVM_CONSTANT_InvokeDynamic = 18
+};
+
+/* JVM_CONSTANT_MethodHandle subtypes */
+enum {
+ JVM_REF_getField = 1,
+ JVM_REF_getStatic = 2,
+ JVM_REF_putField = 3,
+ JVM_REF_putStatic = 4,
+ JVM_REF_invokeVirtual = 5,
+ JVM_REF_invokeStatic = 6,
+ JVM_REF_invokeSpecial = 7,
+ JVM_REF_newInvokeSpecial = 8,
+ JVM_REF_invokeInterface = 9
+};
+
+/* StackMapTable type item numbers */
+
+enum {
+ JVM_ITEM_Top = 0,
+ JVM_ITEM_Integer = 1,
+ JVM_ITEM_Float = 2,
+ JVM_ITEM_Double = 3,
+ JVM_ITEM_Long = 4,
+ JVM_ITEM_Null = 5,
+ JVM_ITEM_UninitializedThis = 6,
+ JVM_ITEM_Object = 7,
+ JVM_ITEM_Uninitialized = 8
+};
+
+/* Type signatures */
+
+enum {
+ JVM_SIGNATURE_ARRAY = '[',
+ JVM_SIGNATURE_BYTE = 'B',
+ JVM_SIGNATURE_CHAR = 'C',
+ JVM_SIGNATURE_CLASS = 'L',
+ JVM_SIGNATURE_ENDCLASS = ';',
+ JVM_SIGNATURE_ENUM = 'E',
+ JVM_SIGNATURE_FLOAT = 'F',
+ JVM_SIGNATURE_DOUBLE = 'D',
+ JVM_SIGNATURE_FUNC = '(',
+ JVM_SIGNATURE_ENDFUNC = ')',
+ JVM_SIGNATURE_INT = 'I',
+ JVM_SIGNATURE_LONG = 'J',
+ JVM_SIGNATURE_SHORT = 'S',
+ JVM_SIGNATURE_VOID = 'V',
+ JVM_SIGNATURE_BOOLEAN = 'Z'
+};
+
+/* Opcodes */
+
+enum {
+ JVM_OPC_nop = 0,
+ JVM_OPC_aconst_null = 1,
+ JVM_OPC_iconst_m1 = 2,
+ JVM_OPC_iconst_0 = 3,
+ JVM_OPC_iconst_1 = 4,
+ JVM_OPC_iconst_2 = 5,
+ JVM_OPC_iconst_3 = 6,
+ JVM_OPC_iconst_4 = 7,
+ JVM_OPC_iconst_5 = 8,
+ JVM_OPC_lconst_0 = 9,
+ JVM_OPC_lconst_1 = 10,
+ JVM_OPC_fconst_0 = 11,
+ JVM_OPC_fconst_1 = 12,
+ JVM_OPC_fconst_2 = 13,
+ JVM_OPC_dconst_0 = 14,
+ JVM_OPC_dconst_1 = 15,
+ JVM_OPC_bipush = 16,
+ JVM_OPC_sipush = 17,
+ JVM_OPC_ldc = 18,
+ JVM_OPC_ldc_w = 19,
+ JVM_OPC_ldc2_w = 20,
+ JVM_OPC_iload = 21,
+ JVM_OPC_lload = 22,
+ JVM_OPC_fload = 23,
+ JVM_OPC_dload = 24,
+ JVM_OPC_aload = 25,
+ JVM_OPC_iload_0 = 26,
+ JVM_OPC_iload_1 = 27,
+ JVM_OPC_iload_2 = 28,
+ JVM_OPC_iload_3 = 29,
+ JVM_OPC_lload_0 = 30,
+ JVM_OPC_lload_1 = 31,
+ JVM_OPC_lload_2 = 32,
+ JVM_OPC_lload_3 = 33,
+ JVM_OPC_fload_0 = 34,
+ JVM_OPC_fload_1 = 35,
+ JVM_OPC_fload_2 = 36,
+ JVM_OPC_fload_3 = 37,
+ JVM_OPC_dload_0 = 38,
+ JVM_OPC_dload_1 = 39,
+ JVM_OPC_dload_2 = 40,
+ JVM_OPC_dload_3 = 41,
+ JVM_OPC_aload_0 = 42,
+ JVM_OPC_aload_1 = 43,
+ JVM_OPC_aload_2 = 44,
+ JVM_OPC_aload_3 = 45,
+ JVM_OPC_iaload = 46,
+ JVM_OPC_laload = 47,
+ JVM_OPC_faload = 48,
+ JVM_OPC_daload = 49,
+ JVM_OPC_aaload = 50,
+ JVM_OPC_baload = 51,
+ JVM_OPC_caload = 52,
+ JVM_OPC_saload = 53,
+ JVM_OPC_istore = 54,
+ JVM_OPC_lstore = 55,
+ JVM_OPC_fstore = 56,
+ JVM_OPC_dstore = 57,
+ JVM_OPC_astore = 58,
+ JVM_OPC_istore_0 = 59,
+ JVM_OPC_istore_1 = 60,
+ JVM_OPC_istore_2 = 61,
+ JVM_OPC_istore_3 = 62,
+ JVM_OPC_lstore_0 = 63,
+ JVM_OPC_lstore_1 = 64,
+ JVM_OPC_lstore_2 = 65,
+ JVM_OPC_lstore_3 = 66,
+ JVM_OPC_fstore_0 = 67,
+ JVM_OPC_fstore_1 = 68,
+ JVM_OPC_fstore_2 = 69,
+ JVM_OPC_fstore_3 = 70,
+ JVM_OPC_dstore_0 = 71,
+ JVM_OPC_dstore_1 = 72,
+ JVM_OPC_dstore_2 = 73,
+ JVM_OPC_dstore_3 = 74,
+ JVM_OPC_astore_0 = 75,
+ JVM_OPC_astore_1 = 76,
+ JVM_OPC_astore_2 = 77,
+ JVM_OPC_astore_3 = 78,
+ JVM_OPC_iastore = 79,
+ JVM_OPC_lastore = 80,
+ JVM_OPC_fastore = 81,
+ JVM_OPC_dastore = 82,
+ JVM_OPC_aastore = 83,
+ JVM_OPC_bastore = 84,
+ JVM_OPC_castore = 85,
+ JVM_OPC_sastore = 86,
+ JVM_OPC_pop = 87,
+ JVM_OPC_pop2 = 88,
+ JVM_OPC_dup = 89,
+ JVM_OPC_dup_x1 = 90,
+ JVM_OPC_dup_x2 = 91,
+ JVM_OPC_dup2 = 92,
+ JVM_OPC_dup2_x1 = 93,
+ JVM_OPC_dup2_x2 = 94,
+ JVM_OPC_swap = 95,
+ JVM_OPC_iadd = 96,
+ JVM_OPC_ladd = 97,
+ JVM_OPC_fadd = 98,
+ JVM_OPC_dadd = 99,
+ JVM_OPC_isub = 100,
+ JVM_OPC_lsub = 101,
+ JVM_OPC_fsub = 102,
+ JVM_OPC_dsub = 103,
+ JVM_OPC_imul = 104,
+ JVM_OPC_lmul = 105,
+ JVM_OPC_fmul = 106,
+ JVM_OPC_dmul = 107,
+ JVM_OPC_idiv = 108,
+ JVM_OPC_ldiv = 109,
+ JVM_OPC_fdiv = 110,
+ JVM_OPC_ddiv = 111,
+ JVM_OPC_irem = 112,
+ JVM_OPC_lrem = 113,
+ JVM_OPC_frem = 114,
+ JVM_OPC_drem = 115,
+ JVM_OPC_ineg = 116,
+ JVM_OPC_lneg = 117,
+ JVM_OPC_fneg = 118,
+ JVM_OPC_dneg = 119,
+ JVM_OPC_ishl = 120,
+ JVM_OPC_lshl = 121,
+ JVM_OPC_ishr = 122,
+ JVM_OPC_lshr = 123,
+ JVM_OPC_iushr = 124,
+ JVM_OPC_lushr = 125,
+ JVM_OPC_iand = 126,
+ JVM_OPC_land = 127,
+ JVM_OPC_ior = 128,
+ JVM_OPC_lor = 129,
+ JVM_OPC_ixor = 130,
+ JVM_OPC_lxor = 131,
+ JVM_OPC_iinc = 132,
+ JVM_OPC_i2l = 133,
+ JVM_OPC_i2f = 134,
+ JVM_OPC_i2d = 135,
+ JVM_OPC_l2i = 136,
+ JVM_OPC_l2f = 137,
+ JVM_OPC_l2d = 138,
+ JVM_OPC_f2i = 139,
+ JVM_OPC_f2l = 140,
+ JVM_OPC_f2d = 141,
+ JVM_OPC_d2i = 142,
+ JVM_OPC_d2l = 143,
+ JVM_OPC_d2f = 144,
+ JVM_OPC_i2b = 145,
+ JVM_OPC_i2c = 146,
+ JVM_OPC_i2s = 147,
+ JVM_OPC_lcmp = 148,
+ JVM_OPC_fcmpl = 149,
+ JVM_OPC_fcmpg = 150,
+ JVM_OPC_dcmpl = 151,
+ JVM_OPC_dcmpg = 152,
+ JVM_OPC_ifeq = 153,
+ JVM_OPC_ifne = 154,
+ JVM_OPC_iflt = 155,
+ JVM_OPC_ifge = 156,
+ JVM_OPC_ifgt = 157,
+ JVM_OPC_ifle = 158,
+ JVM_OPC_if_icmpeq = 159,
+ JVM_OPC_if_icmpne = 160,
+ JVM_OPC_if_icmplt = 161,
+ JVM_OPC_if_icmpge = 162,
+ JVM_OPC_if_icmpgt = 163,
+ JVM_OPC_if_icmple = 164,
+ JVM_OPC_if_acmpeq = 165,
+ JVM_OPC_if_acmpne = 166,
+ JVM_OPC_goto = 167,
+ JVM_OPC_jsr = 168,
+ JVM_OPC_ret = 169,
+ JVM_OPC_tableswitch = 170,
+ JVM_OPC_lookupswitch = 171,
+ JVM_OPC_ireturn = 172,
+ JVM_OPC_lreturn = 173,
+ JVM_OPC_freturn = 174,
+ JVM_OPC_dreturn = 175,
+ JVM_OPC_areturn = 176,
+ JVM_OPC_return = 177,
+ JVM_OPC_getstatic = 178,
+ JVM_OPC_putstatic = 179,
+ JVM_OPC_getfield = 180,
+ JVM_OPC_putfield = 181,
+ JVM_OPC_invokevirtual = 182,
+ JVM_OPC_invokespecial = 183,
+ JVM_OPC_invokestatic = 184,
+ JVM_OPC_invokeinterface = 185,
+ JVM_OPC_invokedynamic = 186,
+ JVM_OPC_new = 187,
+ JVM_OPC_newarray = 188,
+ JVM_OPC_anewarray = 189,
+ JVM_OPC_arraylength = 190,
+ JVM_OPC_athrow = 191,
+ JVM_OPC_checkcast = 192,
+ JVM_OPC_instanceof = 193,
+ JVM_OPC_monitorenter = 194,
+ JVM_OPC_monitorexit = 195,
+ JVM_OPC_wide = 196,
+ JVM_OPC_multianewarray = 197,
+ JVM_OPC_ifnull = 198,
+ JVM_OPC_ifnonnull = 199,
+ JVM_OPC_goto_w = 200,
+ JVM_OPC_jsr_w = 201,
+ JVM_OPC_MAX = 201
+};
+
+/* Opcode length initializer, use with something like:
+ * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER;
+ */
+#define JVM_OPCODE_LENGTH_INITIALIZER { \
+ 1, /* nop */ \
+ 1, /* aconst_null */ \
+ 1, /* iconst_m1 */ \
+ 1, /* iconst_0 */ \
+ 1, /* iconst_1 */ \
+ 1, /* iconst_2 */ \
+ 1, /* iconst_3 */ \
+ 1, /* iconst_4 */ \
+ 1, /* iconst_5 */ \
+ 1, /* lconst_0 */ \
+ 1, /* lconst_1 */ \
+ 1, /* fconst_0 */ \
+ 1, /* fconst_1 */ \
+ 1, /* fconst_2 */ \
+ 1, /* dconst_0 */ \
+ 1, /* dconst_1 */ \
+ 2, /* bipush */ \
+ 3, /* sipush */ \
+ 2, /* ldc */ \
+ 3, /* ldc_w */ \
+ 3, /* ldc2_w */ \
+ 2, /* iload */ \
+ 2, /* lload */ \
+ 2, /* fload */ \
+ 2, /* dload */ \
+ 2, /* aload */ \
+ 1, /* iload_0 */ \
+ 1, /* iload_1 */ \
+ 1, /* iload_2 */ \
+ 1, /* iload_3 */ \
+ 1, /* lload_0 */ \
+ 1, /* lload_1 */ \
+ 1, /* lload_2 */ \
+ 1, /* lload_3 */ \
+ 1, /* fload_0 */ \
+ 1, /* fload_1 */ \
+ 1, /* fload_2 */ \
+ 1, /* fload_3 */ \
+ 1, /* dload_0 */ \
+ 1, /* dload_1 */ \
+ 1, /* dload_2 */ \
+ 1, /* dload_3 */ \
+ 1, /* aload_0 */ \
+ 1, /* aload_1 */ \
+ 1, /* aload_2 */ \
+ 1, /* aload_3 */ \
+ 1, /* iaload */ \
+ 1, /* laload */ \
+ 1, /* faload */ \
+ 1, /* daload */ \
+ 1, /* aaload */ \
+ 1, /* baload */ \
+ 1, /* caload */ \
+ 1, /* saload */ \
+ 2, /* istore */ \
+ 2, /* lstore */ \
+ 2, /* fstore */ \
+ 2, /* dstore */ \
+ 2, /* astore */ \
+ 1, /* istore_0 */ \
+ 1, /* istore_1 */ \
+ 1, /* istore_2 */ \
+ 1, /* istore_3 */ \
+ 1, /* lstore_0 */ \
+ 1, /* lstore_1 */ \
+ 1, /* lstore_2 */ \
+ 1, /* lstore_3 */ \
+ 1, /* fstore_0 */ \
+ 1, /* fstore_1 */ \
+ 1, /* fstore_2 */ \
+ 1, /* fstore_3 */ \
+ 1, /* dstore_0 */ \
+ 1, /* dstore_1 */ \
+ 1, /* dstore_2 */ \
+ 1, /* dstore_3 */ \
+ 1, /* astore_0 */ \
+ 1, /* astore_1 */ \
+ 1, /* astore_2 */ \
+ 1, /* astore_3 */ \
+ 1, /* iastore */ \
+ 1, /* lastore */ \
+ 1, /* fastore */ \
+ 1, /* dastore */ \
+ 1, /* aastore */ \
+ 1, /* bastore */ \
+ 1, /* castore */ \
+ 1, /* sastore */ \
+ 1, /* pop */ \
+ 1, /* pop2 */ \
+ 1, /* dup */ \
+ 1, /* dup_x1 */ \
+ 1, /* dup_x2 */ \
+ 1, /* dup2 */ \
+ 1, /* dup2_x1 */ \
+ 1, /* dup2_x2 */ \
+ 1, /* swap */ \
+ 1, /* iadd */ \
+ 1, /* ladd */ \
+ 1, /* fadd */ \
+ 1, /* dadd */ \
+ 1, /* isub */ \
+ 1, /* lsub */ \
+ 1, /* fsub */ \
+ 1, /* dsub */ \
+ 1, /* imul */ \
+ 1, /* lmul */ \
+ 1, /* fmul */ \
+ 1, /* dmul */ \
+ 1, /* idiv */ \
+ 1, /* ldiv */ \
+ 1, /* fdiv */ \
+ 1, /* ddiv */ \
+ 1, /* irem */ \
+ 1, /* lrem */ \
+ 1, /* frem */ \
+ 1, /* drem */ \
+ 1, /* ineg */ \
+ 1, /* lneg */ \
+ 1, /* fneg */ \
+ 1, /* dneg */ \
+ 1, /* ishl */ \
+ 1, /* lshl */ \
+ 1, /* ishr */ \
+ 1, /* lshr */ \
+ 1, /* iushr */ \
+ 1, /* lushr */ \
+ 1, /* iand */ \
+ 1, /* land */ \
+ 1, /* ior */ \
+ 1, /* lor */ \
+ 1, /* ixor */ \
+ 1, /* lxor */ \
+ 3, /* iinc */ \
+ 1, /* i2l */ \
+ 1, /* i2f */ \
+ 1, /* i2d */ \
+ 1, /* l2i */ \
+ 1, /* l2f */ \
+ 1, /* l2d */ \
+ 1, /* f2i */ \
+ 1, /* f2l */ \
+ 1, /* f2d */ \
+ 1, /* d2i */ \
+ 1, /* d2l */ \
+ 1, /* d2f */ \
+ 1, /* i2b */ \
+ 1, /* i2c */ \
+ 1, /* i2s */ \
+ 1, /* lcmp */ \
+ 1, /* fcmpl */ \
+ 1, /* fcmpg */ \
+ 1, /* dcmpl */ \
+ 1, /* dcmpg */ \
+ 3, /* ifeq */ \
+ 3, /* ifne */ \
+ 3, /* iflt */ \
+ 3, /* ifge */ \
+ 3, /* ifgt */ \
+ 3, /* ifle */ \
+ 3, /* if_icmpeq */ \
+ 3, /* if_icmpne */ \
+ 3, /* if_icmplt */ \
+ 3, /* if_icmpge */ \
+ 3, /* if_icmpgt */ \
+ 3, /* if_icmple */ \
+ 3, /* if_acmpeq */ \
+ 3, /* if_acmpne */ \
+ 3, /* goto */ \
+ 3, /* jsr */ \
+ 2, /* ret */ \
+ 99, /* tableswitch */ \
+ 99, /* lookupswitch */ \
+ 1, /* ireturn */ \
+ 1, /* lreturn */ \
+ 1, /* freturn */ \
+ 1, /* dreturn */ \
+ 1, /* areturn */ \
+ 1, /* return */ \
+ 3, /* getstatic */ \
+ 3, /* putstatic */ \
+ 3, /* getfield */ \
+ 3, /* putfield */ \
+ 3, /* invokevirtual */ \
+ 3, /* invokespecial */ \
+ 3, /* invokestatic */ \
+ 5, /* invokeinterface */ \
+ 5, /* invokedynamic */ \
+ 3, /* new */ \
+ 2, /* newarray */ \
+ 3, /* anewarray */ \
+ 1, /* arraylength */ \
+ 1, /* athrow */ \
+ 3, /* checkcast */ \
+ 3, /* instanceof */ \
+ 1, /* monitorenter */ \
+ 1, /* monitorexit */ \
+ 0, /* wide */ \
+ 4, /* multianewarray */ \
+ 3, /* ifnull */ \
+ 3, /* ifnonnull */ \
+ 5, /* goto_w */ \
+ 5 /* jsr_w */ \
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* CLASSFILE_CONSTANTS */
diff --git a/demos/java/jni/gs_jni/include/jawt.h b/demos/java/jni/gs_jni/include/jawt.h
new file mode 100644
index 00000000..f06e8071
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/jawt.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JAWT_H_
+#define _JAVASOFT_JAWT_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * AWT native interface (new in JDK 1.3)
+ *
+ * The AWT native interface allows a native C or C++ application a means
+ * by which to access native structures in AWT. This is to facilitate moving
+ * legacy C and C++ applications to Java and to target the needs of the
+ * community who, at present, wish to do their own native rendering to canvases
+ * for performance reasons. Standard extensions such as Java3D also require a
+ * means to access the underlying native data structures of AWT.
+ *
+ * There may be future extensions to this API depending on demand.
+ *
+ * A VM does not have to implement this API in order to pass the JCK.
+ * It is recommended, however, that this API is implemented on VMs that support
+ * standard extensions, such as Java3D.
+ *
+ * Since this is a native API, any program which uses it cannot be considered
+ * 100% pure java.
+ */
+
+/*
+ * AWT Native Drawing Surface (JAWT_DrawingSurface).
+ *
+ * For each platform, there is a native drawing surface structure. This
+ * platform-specific structure can be found in jawt_md.h. It is recommended
+ * that additional platforms follow the same model. It is also recommended
+ * that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
+ *
+ *******************
+ * EXAMPLE OF USAGE:
+ *******************
+ *
+ * In Win32, a programmer wishes to access the HWND of a canvas to perform
+ * native rendering into it. The programmer has declared the paint() method
+ * for their canvas subclass to be native:
+ *
+ *
+ * MyCanvas.java:
+ *
+ * import java.awt.*;
+ *
+ * public class MyCanvas extends Canvas {
+ *
+ * static {
+ * System.loadLibrary("mylib");
+ * }
+ *
+ * public native void paint(Graphics g);
+ * }
+ *
+ *
+ * myfile.c:
+ *
+ * #include "jawt_md.h"
+ * #include <assert.h>
+ *
+ * JNIEXPORT void JNICALL
+ * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
+ * {
+ * JAWT awt;
+ * JAWT_DrawingSurface* ds;
+ * JAWT_DrawingSurfaceInfo* dsi;
+ * JAWT_Win32DrawingSurfaceInfo* dsi_win;
+ * jboolean result;
+ * jint lock;
+ *
+ * // Get the AWT
+ * awt.version = JAWT_VERSION_1_3;
+ * result = JAWT_GetAWT(env, &awt);
+ * assert(result != JNI_FALSE);
+ *
+ * // Get the drawing surface
+ * ds = awt.GetDrawingSurface(env, canvas);
+ * assert(ds != NULL);
+ *
+ * // Lock the drawing surface
+ * lock = ds->Lock(ds);
+ * assert((lock & JAWT_LOCK_ERROR) == 0);
+ *
+ * // Get the drawing surface info
+ * dsi = ds->GetDrawingSurfaceInfo(ds);
+ *
+ * // Get the platform-specific drawing info
+ * dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+ *
+ * //////////////////////////////
+ * // !!! DO PAINTING HERE !!! //
+ * //////////////////////////////
+ *
+ * // Free the drawing surface info
+ * ds->FreeDrawingSurfaceInfo(dsi);
+ *
+ * // Unlock the drawing surface
+ * ds->Unlock(ds);
+ *
+ * // Free the drawing surface
+ * awt.FreeDrawingSurface(ds);
+ * }
+ *
+ */
+
+/*
+ * JAWT_Rectangle
+ * Structure for a native rectangle.
+ */
+typedef struct jawt_Rectangle {
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+} JAWT_Rectangle;
+
+struct jawt_DrawingSurface;
+
+/*
+ * JAWT_DrawingSurfaceInfo
+ * Structure for containing the underlying drawing information of a component.
+ */
+typedef struct jawt_DrawingSurfaceInfo {
+ /*
+ * Pointer to the platform-specific information. This can be safely
+ * cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
+ * JAWT_X11DrawingSurfaceInfo on Solaris. On Mac OS X this is a
+ * pointer to a NSObject that conforms to the JAWT_SurfaceLayers
+ * protocol. See jawt_md.h for details.
+ */
+ void* platformInfo;
+ /* Cached pointer to the underlying drawing surface */
+ struct jawt_DrawingSurface* ds;
+ /* Bounding rectangle of the drawing surface */
+ JAWT_Rectangle bounds;
+ /* Number of rectangles in the clip */
+ jint clipSize;
+ /* Clip rectangle array */
+ JAWT_Rectangle* clip;
+} JAWT_DrawingSurfaceInfo;
+
+#define JAWT_LOCK_ERROR 0x00000001
+#define JAWT_LOCK_CLIP_CHANGED 0x00000002
+#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
+#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
+
+/*
+ * JAWT_DrawingSurface
+ * Structure for containing the underlying drawing information of a component.
+ * All operations on a JAWT_DrawingSurface MUST be performed from the same
+ * thread as the call to GetDrawingSurface.
+ */
+typedef struct jawt_DrawingSurface {
+ /*
+ * Cached reference to the Java environment of the calling thread.
+ * If Lock(), Unlock(), GetDrawingSurfaceInfo() or
+ * FreeDrawingSurfaceInfo() are called from a different thread,
+ * this data member should be set before calling those functions.
+ */
+ JNIEnv* env;
+ /* Cached reference to the target object */
+ jobject target;
+ /*
+ * Lock the surface of the target component for native rendering.
+ * When finished drawing, the surface must be unlocked with
+ * Unlock(). This function returns a bitmask with one or more of the
+ * following values:
+ *
+ * JAWT_LOCK_ERROR - When an error has occurred and the surface could not
+ * be locked.
+ *
+ * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
+ *
+ * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
+ *
+ * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
+ */
+ jint (JNICALL *Lock)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Get the drawing surface info.
+ * The value returned may be cached, but the values may change if
+ * additional calls to Lock() or Unlock() are made.
+ * Lock() must be called before this can return a valid value.
+ * Returns NULL if an error has occurred.
+ * When finished with the returned value, FreeDrawingSurfaceInfo must be
+ * called.
+ */
+ JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Free the drawing surface info.
+ */
+ void (JNICALL *FreeDrawingSurfaceInfo)
+ (JAWT_DrawingSurfaceInfo* dsi);
+ /*
+ * Unlock the drawing surface of the target component for native rendering.
+ */
+ void (JNICALL *Unlock)
+ (struct jawt_DrawingSurface* ds);
+} JAWT_DrawingSurface;
+
+/*
+ * JAWT
+ * Structure for containing native AWT functions.
+ */
+typedef struct jawt {
+ /*
+ * Version of this structure. This must always be set before
+ * calling JAWT_GetAWT()
+ */
+ jint version;
+ /*
+ * Return a drawing surface from a target jobject. This value
+ * may be cached.
+ * Returns NULL if an error has occurred.
+ * Target must be a java.awt.Component (should be a Canvas
+ * or Window for native rendering).
+ * FreeDrawingSurface() must be called when finished with the
+ * returned JAWT_DrawingSurface.
+ */
+ JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
+ (JNIEnv* env, jobject target);
+ /*
+ * Free the drawing surface allocated in GetDrawingSurface.
+ */
+ void (JNICALL *FreeDrawingSurface)
+ (JAWT_DrawingSurface* ds);
+ /*
+ * Since 1.4
+ * Locks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Lock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Unlocks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Unlock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Returns a reference to a java.awt.Component from a native
+ * platform handle. On Windows, this corresponds to an HWND;
+ * on Solaris and Linux, this is a Drawable. For other platforms,
+ * see the appropriate machine-dependent header file for a description.
+ * The reference returned by this function is a local
+ * reference that is only valid in this environment.
+ * This function returns a NULL reference if no component could be
+ * found with matching platform information.
+ */
+ jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
+
+} JAWT;
+
+/*
+ * Get the AWT native structure. This function returns JNI_FALSE if
+ * an error occurs.
+ */
+_JNI_IMPORT_OR_EXPORT_
+jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
+
+#define JAWT_VERSION_1_3 0x00010003
+#define JAWT_VERSION_1_4 0x00010004
+#define JAWT_VERSION_1_7 0x00010007
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* !_JAVASOFT_JAWT_H_ */
diff --git a/demos/java/jni/gs_jni/include/jdwpTransport.h b/demos/java/jni/gs_jni/include/jdwpTransport.h
new file mode 100644
index 00000000..4f4b92ed
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/jdwpTransport.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Java Debug Wire Protocol Transport Service Provider Interface.
+ */
+
+#ifndef JDWPTRANSPORT_H
+#define JDWPTRANSPORT_H
+
+#include "jni.h"
+
+enum {
+ JDWPTRANSPORT_VERSION_1_0 = 0x00010000
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct jdwpTransportNativeInterface_;
+
+struct _jdwpTransportEnv;
+
+#ifdef __cplusplus
+typedef _jdwpTransportEnv jdwpTransportEnv;
+#else
+typedef const struct jdwpTransportNativeInterface_ *jdwpTransportEnv;
+#endif /* __cplusplus */
+
+/*
+ * Errors. Universal errors with JVMTI/JVMDI equivalents keep the
+ * values the same.
+ */
+typedef enum {
+ JDWPTRANSPORT_ERROR_NONE = 0,
+ JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103,
+ JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110,
+ JDWPTRANSPORT_ERROR_INTERNAL = 113,
+ JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201,
+ JDWPTRANSPORT_ERROR_IO_ERROR = 202,
+ JDWPTRANSPORT_ERROR_TIMEOUT = 203,
+ JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204
+} jdwpTransportError;
+
+
+/*
+ * Structure to define capabilities
+ */
+typedef struct {
+ unsigned int can_timeout_attach :1;
+ unsigned int can_timeout_accept :1;
+ unsigned int can_timeout_handshake :1;
+ unsigned int reserved3 :1;
+ unsigned int reserved4 :1;
+ unsigned int reserved5 :1;
+ unsigned int reserved6 :1;
+ unsigned int reserved7 :1;
+ unsigned int reserved8 :1;
+ unsigned int reserved9 :1;
+ unsigned int reserved10 :1;
+ unsigned int reserved11 :1;
+ unsigned int reserved12 :1;
+ unsigned int reserved13 :1;
+ unsigned int reserved14 :1;
+ unsigned int reserved15 :1;
+} JDWPTransportCapabilities;
+
+
+/*
+ * Structures to define packet layout.
+ *
+ * See: http://java.sun.com/j2se/1.5/docs/guide/jpda/jdwp-spec.html
+ */
+
+enum {
+ /*
+ * If additional flags are added that apply to jdwpCmdPacket,
+ * then debugLoop.c: reader() will need to be updated to
+ * accept more than JDWPTRANSPORT_FLAGS_NONE.
+ */
+ JDWPTRANSPORT_FLAGS_NONE = 0x0,
+ JDWPTRANSPORT_FLAGS_REPLY = 0x80
+};
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jbyte cmdSet;
+ jbyte cmd;
+ jbyte *data;
+} jdwpCmdPacket;
+
+typedef struct {
+ jint len;
+ jint id;
+ jbyte flags;
+ jshort errorCode;
+ jbyte *data;
+} jdwpReplyPacket;
+
+typedef struct {
+ union {
+ jdwpCmdPacket cmd;
+ jdwpReplyPacket reply;
+ } type;
+} jdwpPacket;
+
+/*
+ * JDWP functions called by the transport.
+ */
+typedef struct jdwpTransportCallback {
+ void *(*alloc)(jint numBytes); /* Call this for all allocations */
+ void (*free)(void *buffer); /* Call this for all deallocations */
+} jdwpTransportCallback;
+
+typedef jint (JNICALL *jdwpTransport_OnLoad_t)(JavaVM *jvm,
+ jdwpTransportCallback *callback,
+ jint version,
+ jdwpTransportEnv** env);
+
+
+
+/* Function Interface */
+
+struct jdwpTransportNativeInterface_ {
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Get Capabilities */
+ jdwpTransportError (JNICALL *GetCapabilities)(jdwpTransportEnv* env,
+ JDWPTransportCapabilities *capabilities_ptr);
+
+ /* 3 : Attach */
+ jdwpTransportError (JNICALL *Attach)(jdwpTransportEnv* env,
+ const char* address,
+ jlong attach_timeout,
+ jlong handshake_timeout);
+
+ /* 4: StartListening */
+ jdwpTransportError (JNICALL *StartListening)(jdwpTransportEnv* env,
+ const char* address,
+ char** actual_address);
+
+ /* 5: StopListening */
+ jdwpTransportError (JNICALL *StopListening)(jdwpTransportEnv* env);
+
+ /* 6: Accept */
+ jdwpTransportError (JNICALL *Accept)(jdwpTransportEnv* env,
+ jlong accept_timeout,
+ jlong handshake_timeout);
+
+ /* 7: IsOpen */
+ jboolean (JNICALL *IsOpen)(jdwpTransportEnv* env);
+
+ /* 8: Close */
+ jdwpTransportError (JNICALL *Close)(jdwpTransportEnv* env);
+
+ /* 9: ReadPacket */
+ jdwpTransportError (JNICALL *ReadPacket)(jdwpTransportEnv* env,
+ jdwpPacket *pkt);
+
+ /* 10: Write Packet */
+ jdwpTransportError (JNICALL *WritePacket)(jdwpTransportEnv* env,
+ const jdwpPacket* pkt);
+
+ /* 11: GetLastError */
+ jdwpTransportError (JNICALL *GetLastError)(jdwpTransportEnv* env,
+ char** error);
+
+};
+
+
+/*
+ * Use inlined functions so that C++ code can use syntax such as
+ * env->Attach("mymachine:5000", 10*1000, 0);
+ *
+ * rather than using C's :-
+ *
+ * (*env)->Attach(env, "mymachine:5000", 10*1000, 0);
+ */
+struct _jdwpTransportEnv {
+ const struct jdwpTransportNativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jdwpTransportError GetCapabilities(JDWPTransportCapabilities *capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jdwpTransportError Attach(const char* address, jlong attach_timeout,
+ jlong handshake_timeout) {
+ return functions->Attach(this, address, attach_timeout, handshake_timeout);
+ }
+
+ jdwpTransportError StartListening(const char* address,
+ char** actual_address) {
+ return functions->StartListening(this, address, actual_address);
+ }
+
+ jdwpTransportError StopListening(void) {
+ return functions->StopListening(this);
+ }
+
+ jdwpTransportError Accept(jlong accept_timeout, jlong handshake_timeout) {
+ return functions->Accept(this, accept_timeout, handshake_timeout);
+ }
+
+ jboolean IsOpen(void) {
+ return functions->IsOpen(this);
+ }
+
+ jdwpTransportError Close(void) {
+ return functions->Close(this);
+ }
+
+ jdwpTransportError ReadPacket(jdwpPacket *pkt) {
+ return functions->ReadPacket(this, pkt);
+ }
+
+ jdwpTransportError WritePacket(const jdwpPacket* pkt) {
+ return functions->WritePacket(this, pkt);
+ }
+
+ jdwpTransportError GetLastError(char** error) {
+ return functions->GetLastError(this, error);
+ }
+
+
+#endif /* __cplusplus */
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* JDWPTRANSPORT_H */
diff --git a/demos/java/jni/gs_jni/include/jni.h b/demos/java/jni/gs_jni/include/jni.h
new file mode 100644
index 00000000..97b14d8a
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/jni.h
@@ -0,0 +1,1964 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#ifdef _WIN32
+#include "win32/jni_md.h"
+#else
+#include "jni_md.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+
+ /* New JNI 1.6 Features */
+
+ jobjectRefType (JNICALL *GetObjectRefType)
+ (JNIEnv* env, jobject obj);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+ jobjectRefType GetObjectRefType(jobject obj) {
+ return functions->GetObjectRefType(this, obj);
+ }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+#define JNI_VERSION_1_8 0x00010008
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
diff --git a/demos/java/jni/gs_jni/include/jvmti.h b/demos/java/jni/gs_jni/include/jvmti.h
new file mode 100644
index 00000000..e8de8585
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/jvmti.h
@@ -0,0 +1,2533 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
+
+
+ /* Include file for the Java(tm) Virtual Machine Tool Interface */
+
+#ifndef _JAVA_JVMTI_H_
+#define _JAVA_JVMTI_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ JVMTI_VERSION_1 = 0x30010000,
+ JVMTI_VERSION_1_0 = 0x30010000,
+ JVMTI_VERSION_1_1 = 0x30010100,
+ JVMTI_VERSION_1_2 = 0x30010200,
+
+ JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */
+};
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
+
+JNIEXPORT void JNICALL
+Agent_OnUnload(JavaVM *vm);
+
+ /* Forward declaration of the environment */
+
+struct _jvmtiEnv;
+
+struct jvmtiInterface_1_;
+
+#ifdef __cplusplus
+typedef _jvmtiEnv jvmtiEnv;
+#else
+typedef const struct jvmtiInterface_1_ *jvmtiEnv;
+#endif /* __cplusplus */
+
+/* Derived Base Types */
+
+typedef jobject jthread;
+typedef jobject jthreadGroup;
+typedef jlong jlocation;
+struct _jrawMonitorID;
+typedef struct _jrawMonitorID *jrawMonitorID;
+typedef struct JNINativeInterface_ jniNativeInterface;
+
+ /* Constants */
+
+
+ /* Thread State Flags */
+
+enum {
+ JVMTI_THREAD_STATE_ALIVE = 0x0001,
+ JVMTI_THREAD_STATE_TERMINATED = 0x0002,
+ JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
+ JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
+ JVMTI_THREAD_STATE_WAITING = 0x0080,
+ JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
+ JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
+ JVMTI_THREAD_STATE_SLEEPING = 0x0040,
+ JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
+ JVMTI_THREAD_STATE_PARKED = 0x0200,
+ JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
+ JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
+ JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
+ JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
+ JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
+ JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000
+};
+
+ /* java.lang.Thread.State Conversion Masks */
+
+enum {
+ JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
+ JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
+ JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
+ JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE,
+ JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
+ JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
+ JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
+};
+
+ /* Thread Priority Constants */
+
+enum {
+ JVMTI_THREAD_MIN_PRIORITY = 1,
+ JVMTI_THREAD_NORM_PRIORITY = 5,
+ JVMTI_THREAD_MAX_PRIORITY = 10
+};
+
+ /* Heap Filter Flags */
+
+enum {
+ JVMTI_HEAP_FILTER_TAGGED = 0x4,
+ JVMTI_HEAP_FILTER_UNTAGGED = 0x8,
+ JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10,
+ JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20
+};
+
+ /* Heap Visit Control Flags */
+
+enum {
+ JVMTI_VISIT_OBJECTS = 0x100,
+ JVMTI_VISIT_ABORT = 0x8000
+};
+
+ /* Heap Reference Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_REFERENCE_CLASS = 1,
+ JVMTI_HEAP_REFERENCE_FIELD = 2,
+ JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_HEAP_REFERENCE_SIGNERS = 5,
+ JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_HEAP_REFERENCE_INTERFACE = 7,
+ JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9,
+ JVMTI_HEAP_REFERENCE_SUPERCLASS = 10,
+ JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21,
+ JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22,
+ JVMTI_HEAP_REFERENCE_MONITOR = 23,
+ JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24,
+ JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25,
+ JVMTI_HEAP_REFERENCE_THREAD = 26,
+ JVMTI_HEAP_REFERENCE_OTHER = 27
+} jvmtiHeapReferenceKind;
+
+ /* Primitive Type Enumeration */
+
+typedef enum {
+ JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90,
+ JVMTI_PRIMITIVE_TYPE_BYTE = 66,
+ JVMTI_PRIMITIVE_TYPE_CHAR = 67,
+ JVMTI_PRIMITIVE_TYPE_SHORT = 83,
+ JVMTI_PRIMITIVE_TYPE_INT = 73,
+ JVMTI_PRIMITIVE_TYPE_LONG = 74,
+ JVMTI_PRIMITIVE_TYPE_FLOAT = 70,
+ JVMTI_PRIMITIVE_TYPE_DOUBLE = 68
+} jvmtiPrimitiveType;
+
+ /* Heap Object Filter Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_OBJECT_TAGGED = 1,
+ JVMTI_HEAP_OBJECT_UNTAGGED = 2,
+ JVMTI_HEAP_OBJECT_EITHER = 3
+} jvmtiHeapObjectFilter;
+
+ /* Heap Root Kind Enumeration */
+
+typedef enum {
+ JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
+ JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
+ JVMTI_HEAP_ROOT_MONITOR = 3,
+ JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
+ JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
+ JVMTI_HEAP_ROOT_THREAD = 6,
+ JVMTI_HEAP_ROOT_OTHER = 7
+} jvmtiHeapRootKind;
+
+ /* Object Reference Enumeration */
+
+typedef enum {
+ JVMTI_REFERENCE_CLASS = 1,
+ JVMTI_REFERENCE_FIELD = 2,
+ JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_REFERENCE_SIGNERS = 5,
+ JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_REFERENCE_INTERFACE = 7,
+ JVMTI_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_REFERENCE_CONSTANT_POOL = 9
+} jvmtiObjectReferenceKind;
+
+ /* Iteration Control Enumeration */
+
+typedef enum {
+ JVMTI_ITERATION_CONTINUE = 1,
+ JVMTI_ITERATION_IGNORE = 2,
+ JVMTI_ITERATION_ABORT = 0
+} jvmtiIterationControl;
+
+ /* Class Status Flags */
+
+enum {
+ JVMTI_CLASS_STATUS_VERIFIED = 1,
+ JVMTI_CLASS_STATUS_PREPARED = 2,
+ JVMTI_CLASS_STATUS_INITIALIZED = 4,
+ JVMTI_CLASS_STATUS_ERROR = 8,
+ JVMTI_CLASS_STATUS_ARRAY = 16,
+ JVMTI_CLASS_STATUS_PRIMITIVE = 32
+};
+
+ /* Event Enable/Disable */
+
+typedef enum {
+ JVMTI_ENABLE = 1,
+ JVMTI_DISABLE = 0
+} jvmtiEventMode;
+
+ /* Extension Function/Event Parameter Types */
+
+typedef enum {
+ JVMTI_TYPE_JBYTE = 101,
+ JVMTI_TYPE_JCHAR = 102,
+ JVMTI_TYPE_JSHORT = 103,
+ JVMTI_TYPE_JINT = 104,
+ JVMTI_TYPE_JLONG = 105,
+ JVMTI_TYPE_JFLOAT = 106,
+ JVMTI_TYPE_JDOUBLE = 107,
+ JVMTI_TYPE_JBOOLEAN = 108,
+ JVMTI_TYPE_JOBJECT = 109,
+ JVMTI_TYPE_JTHREAD = 110,
+ JVMTI_TYPE_JCLASS = 111,
+ JVMTI_TYPE_JVALUE = 112,
+ JVMTI_TYPE_JFIELDID = 113,
+ JVMTI_TYPE_JMETHODID = 114,
+ JVMTI_TYPE_CCHAR = 115,
+ JVMTI_TYPE_CVOID = 116,
+ JVMTI_TYPE_JNIENV = 117
+} jvmtiParamTypes;
+
+ /* Extension Function/Event Parameter Kinds */
+
+typedef enum {
+ JVMTI_KIND_IN = 91,
+ JVMTI_KIND_IN_PTR = 92,
+ JVMTI_KIND_IN_BUF = 93,
+ JVMTI_KIND_ALLOC_BUF = 94,
+ JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
+ JVMTI_KIND_OUT = 96,
+ JVMTI_KIND_OUT_BUF = 97
+} jvmtiParamKind;
+
+ /* Timer Kinds */
+
+typedef enum {
+ JVMTI_TIMER_USER_CPU = 30,
+ JVMTI_TIMER_TOTAL_CPU = 31,
+ JVMTI_TIMER_ELAPSED = 32
+} jvmtiTimerKind;
+
+ /* Phases of execution */
+
+typedef enum {
+ JVMTI_PHASE_ONLOAD = 1,
+ JVMTI_PHASE_PRIMORDIAL = 2,
+ JVMTI_PHASE_START = 6,
+ JVMTI_PHASE_LIVE = 4,
+ JVMTI_PHASE_DEAD = 8
+} jvmtiPhase;
+
+ /* Version Interface Types */
+
+enum {
+ JVMTI_VERSION_INTERFACE_JNI = 0x00000000,
+ JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000
+};
+
+ /* Version Masks */
+
+enum {
+ JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000,
+ JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000,
+ JVMTI_VERSION_MASK_MINOR = 0x0000FF00,
+ JVMTI_VERSION_MASK_MICRO = 0x000000FF
+};
+
+ /* Version Shifts */
+
+enum {
+ JVMTI_VERSION_SHIFT_MAJOR = 16,
+ JVMTI_VERSION_SHIFT_MINOR = 8,
+ JVMTI_VERSION_SHIFT_MICRO = 0
+};
+
+ /* Verbose Flag Enumeration */
+
+typedef enum {
+ JVMTI_VERBOSE_OTHER = 0,
+ JVMTI_VERBOSE_GC = 1,
+ JVMTI_VERBOSE_CLASS = 2,
+ JVMTI_VERBOSE_JNI = 4
+} jvmtiVerboseFlag;
+
+ /* JLocation Format Enumeration */
+
+typedef enum {
+ JVMTI_JLOCATION_JVMBCI = 1,
+ JVMTI_JLOCATION_MACHINEPC = 2,
+ JVMTI_JLOCATION_OTHER = 0
+} jvmtiJlocationFormat;
+
+ /* Resource Exhaustion Flags */
+
+enum {
+ JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001,
+ JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002,
+ JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004
+};
+
+ /* Errors */
+
+typedef enum {
+ JVMTI_ERROR_NONE = 0,
+ JVMTI_ERROR_INVALID_THREAD = 10,
+ JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
+ JVMTI_ERROR_INVALID_PRIORITY = 12,
+ JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
+ JVMTI_ERROR_THREAD_SUSPENDED = 14,
+ JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
+ JVMTI_ERROR_INVALID_OBJECT = 20,
+ JVMTI_ERROR_INVALID_CLASS = 21,
+ JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
+ JVMTI_ERROR_INVALID_METHODID = 23,
+ JVMTI_ERROR_INVALID_LOCATION = 24,
+ JVMTI_ERROR_INVALID_FIELDID = 25,
+ JVMTI_ERROR_NO_MORE_FRAMES = 31,
+ JVMTI_ERROR_OPAQUE_FRAME = 32,
+ JVMTI_ERROR_TYPE_MISMATCH = 34,
+ JVMTI_ERROR_INVALID_SLOT = 35,
+ JVMTI_ERROR_DUPLICATE = 40,
+ JVMTI_ERROR_NOT_FOUND = 41,
+ JVMTI_ERROR_INVALID_MONITOR = 50,
+ JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
+ JVMTI_ERROR_INTERRUPT = 52,
+ JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
+ JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
+ JVMTI_ERROR_FAILS_VERIFICATION = 62,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
+ JVMTI_ERROR_INVALID_TYPESTATE = 65,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
+ JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
+ JVMTI_ERROR_NAMES_DONT_MATCH = 69,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
+ JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
+ JVMTI_ERROR_NOT_AVAILABLE = 98,
+ JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
+ JVMTI_ERROR_NULL_POINTER = 100,
+ JVMTI_ERROR_ABSENT_INFORMATION = 101,
+ JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
+ JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
+ JVMTI_ERROR_NATIVE_METHOD = 104,
+ JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106,
+ JVMTI_ERROR_OUT_OF_MEMORY = 110,
+ JVMTI_ERROR_ACCESS_DENIED = 111,
+ JVMTI_ERROR_WRONG_PHASE = 112,
+ JVMTI_ERROR_INTERNAL = 113,
+ JVMTI_ERROR_UNATTACHED_THREAD = 115,
+ JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
+ JVMTI_ERROR_MAX = 116
+} jvmtiError;
+
+ /* Event IDs */
+
+typedef enum {
+ JVMTI_MIN_EVENT_TYPE_VAL = 50,
+ JVMTI_EVENT_VM_INIT = 50,
+ JVMTI_EVENT_VM_DEATH = 51,
+ JVMTI_EVENT_THREAD_START = 52,
+ JVMTI_EVENT_THREAD_END = 53,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
+ JVMTI_EVENT_CLASS_LOAD = 55,
+ JVMTI_EVENT_CLASS_PREPARE = 56,
+ JVMTI_EVENT_VM_START = 57,
+ JVMTI_EVENT_EXCEPTION = 58,
+ JVMTI_EVENT_EXCEPTION_CATCH = 59,
+ JVMTI_EVENT_SINGLE_STEP = 60,
+ JVMTI_EVENT_FRAME_POP = 61,
+ JVMTI_EVENT_BREAKPOINT = 62,
+ JVMTI_EVENT_FIELD_ACCESS = 63,
+ JVMTI_EVENT_FIELD_MODIFICATION = 64,
+ JVMTI_EVENT_METHOD_ENTRY = 65,
+ JVMTI_EVENT_METHOD_EXIT = 66,
+ JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
+ JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
+ JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
+ JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
+ JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
+ JVMTI_EVENT_MONITOR_WAIT = 73,
+ JVMTI_EVENT_MONITOR_WAITED = 74,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
+ JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
+ JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
+ JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
+ JVMTI_EVENT_OBJECT_FREE = 83,
+ JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
+ JVMTI_MAX_EVENT_TYPE_VAL = 84
+} jvmtiEvent;
+
+
+ /* Pre-Declarations */
+struct _jvmtiThreadInfo;
+typedef struct _jvmtiThreadInfo jvmtiThreadInfo;
+struct _jvmtiMonitorStackDepthInfo;
+typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo;
+struct _jvmtiThreadGroupInfo;
+typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo;
+struct _jvmtiFrameInfo;
+typedef struct _jvmtiFrameInfo jvmtiFrameInfo;
+struct _jvmtiStackInfo;
+typedef struct _jvmtiStackInfo jvmtiStackInfo;
+struct _jvmtiHeapReferenceInfoField;
+typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField;
+struct _jvmtiHeapReferenceInfoArray;
+typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray;
+struct _jvmtiHeapReferenceInfoConstantPool;
+typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool;
+struct _jvmtiHeapReferenceInfoStackLocal;
+typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal;
+struct _jvmtiHeapReferenceInfoJniLocal;
+typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal;
+struct _jvmtiHeapReferenceInfoReserved;
+typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved;
+union _jvmtiHeapReferenceInfo;
+typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo;
+struct _jvmtiHeapCallbacks;
+typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks;
+struct _jvmtiClassDefinition;
+typedef struct _jvmtiClassDefinition jvmtiClassDefinition;
+struct _jvmtiMonitorUsage;
+typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage;
+struct _jvmtiLineNumberEntry;
+typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry;
+struct _jvmtiLocalVariableEntry;
+typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry;
+struct _jvmtiParamInfo;
+typedef struct _jvmtiParamInfo jvmtiParamInfo;
+struct _jvmtiExtensionFunctionInfo;
+typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo;
+struct _jvmtiExtensionEventInfo;
+typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo;
+struct _jvmtiTimerInfo;
+typedef struct _jvmtiTimerInfo jvmtiTimerInfo;
+struct _jvmtiAddrLocationMap;
+typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
+
+ /* Function Types */
+
+typedef void (JNICALL *jvmtiStartFunction)
+ (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
+
+typedef jint (JNICALL *jvmtiHeapIterationCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiHeapReferenceCallback)
+ (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
+
+typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
+ (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
+
+typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
+
+typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);
+
+typedef jint (JNICALL *jvmtiReservedCallback)
+ ();
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
+ (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
+ (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
+
+typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
+ (jvmtiEnv* jvmti_env, ...);
+
+typedef void (JNICALL *jvmtiExtensionEvent)
+ (jvmtiEnv* jvmti_env, ...);
+
+
+ /* Structure Types */
+struct _jvmtiThreadInfo {
+ char* name;
+ jint priority;
+ jboolean is_daemon;
+ jthreadGroup thread_group;
+ jobject context_class_loader;
+};
+struct _jvmtiMonitorStackDepthInfo {
+ jobject monitor;
+ jint stack_depth;
+};
+struct _jvmtiThreadGroupInfo {
+ jthreadGroup parent;
+ char* name;
+ jint max_priority;
+ jboolean is_daemon;
+};
+struct _jvmtiFrameInfo {
+ jmethodID method;
+ jlocation location;
+};
+struct _jvmtiStackInfo {
+ jthread thread;
+ jint state;
+ jvmtiFrameInfo* frame_buffer;
+ jint frame_count;
+};
+struct _jvmtiHeapReferenceInfoField {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoArray {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoConstantPool {
+ jint index;
+};
+struct _jvmtiHeapReferenceInfoStackLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+ jlocation location;
+ jint slot;
+};
+struct _jvmtiHeapReferenceInfoJniLocal {
+ jlong thread_tag;
+ jlong thread_id;
+ jint depth;
+ jmethodID method;
+};
+struct _jvmtiHeapReferenceInfoReserved {
+ jlong reserved1;
+ jlong reserved2;
+ jlong reserved3;
+ jlong reserved4;
+ jlong reserved5;
+ jlong reserved6;
+ jlong reserved7;
+ jlong reserved8;
+};
+union _jvmtiHeapReferenceInfo {
+ jvmtiHeapReferenceInfoField field;
+ jvmtiHeapReferenceInfoArray array;
+ jvmtiHeapReferenceInfoConstantPool constant_pool;
+ jvmtiHeapReferenceInfoStackLocal stack_local;
+ jvmtiHeapReferenceInfoJniLocal jni_local;
+ jvmtiHeapReferenceInfoReserved other;
+};
+struct _jvmtiHeapCallbacks {
+ jvmtiHeapIterationCallback heap_iteration_callback;
+ jvmtiHeapReferenceCallback heap_reference_callback;
+ jvmtiPrimitiveFieldCallback primitive_field_callback;
+ jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
+ jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
+ jvmtiReservedCallback reserved5;
+ jvmtiReservedCallback reserved6;
+ jvmtiReservedCallback reserved7;
+ jvmtiReservedCallback reserved8;
+ jvmtiReservedCallback reserved9;
+ jvmtiReservedCallback reserved10;
+ jvmtiReservedCallback reserved11;
+ jvmtiReservedCallback reserved12;
+ jvmtiReservedCallback reserved13;
+ jvmtiReservedCallback reserved14;
+ jvmtiReservedCallback reserved15;
+};
+struct _jvmtiClassDefinition {
+ jclass klass;
+ jint class_byte_count;
+ const unsigned char* class_bytes;
+};
+struct _jvmtiMonitorUsage {
+ jthread owner;
+ jint entry_count;
+ jint waiter_count;
+ jthread* waiters;
+ jint notify_waiter_count;
+ jthread* notify_waiters;
+};
+struct _jvmtiLineNumberEntry {
+ jlocation start_location;
+ jint line_number;
+};
+struct _jvmtiLocalVariableEntry {
+ jlocation start_location;
+ jint length;
+ char* name;
+ char* signature;
+ char* generic_signature;
+ jint slot;
+};
+struct _jvmtiParamInfo {
+ char* name;
+ jvmtiParamKind kind;
+ jvmtiParamTypes base_type;
+ jboolean null_ok;
+};
+struct _jvmtiExtensionFunctionInfo {
+ jvmtiExtensionFunction func;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+ jint error_count;
+ jvmtiError* errors;
+};
+struct _jvmtiExtensionEventInfo {
+ jint extension_event_index;
+ char* id;
+ char* short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+};
+struct _jvmtiTimerInfo {
+ jlong max_value;
+ jboolean may_skip_forward;
+ jboolean may_skip_backward;
+ jvmtiTimerKind kind;
+ jlong reserved1;
+ jlong reserved2;
+};
+struct _jvmtiAddrLocationMap {
+ const void* start_address;
+ jlocation location;
+};
+
+typedef struct {
+ unsigned int can_tag_objects : 1;
+ unsigned int can_generate_field_modification_events : 1;
+ unsigned int can_generate_field_access_events : 1;
+ unsigned int can_get_bytecodes : 1;
+ unsigned int can_get_synthetic_attribute : 1;
+ unsigned int can_get_owned_monitor_info : 1;
+ unsigned int can_get_current_contended_monitor : 1;
+ unsigned int can_get_monitor_info : 1;
+ unsigned int can_pop_frame : 1;
+ unsigned int can_redefine_classes : 1;
+ unsigned int can_signal_thread : 1;
+ unsigned int can_get_source_file_name : 1;
+ unsigned int can_get_line_numbers : 1;
+ unsigned int can_get_source_debug_extension : 1;
+ unsigned int can_access_local_variables : 1;
+ unsigned int can_maintain_original_method_order : 1;
+ unsigned int can_generate_single_step_events : 1;
+ unsigned int can_generate_exception_events : 1;
+ unsigned int can_generate_frame_pop_events : 1;
+ unsigned int can_generate_breakpoint_events : 1;
+ unsigned int can_suspend : 1;
+ unsigned int can_redefine_any_class : 1;
+ unsigned int can_get_current_thread_cpu_time : 1;
+ unsigned int can_get_thread_cpu_time : 1;
+ unsigned int can_generate_method_entry_events : 1;
+ unsigned int can_generate_method_exit_events : 1;
+ unsigned int can_generate_all_class_hook_events : 1;
+ unsigned int can_generate_compiled_method_load_events : 1;
+ unsigned int can_generate_monitor_events : 1;
+ unsigned int can_generate_vm_object_alloc_events : 1;
+ unsigned int can_generate_native_method_bind_events : 1;
+ unsigned int can_generate_garbage_collection_events : 1;
+ unsigned int can_generate_object_free_events : 1;
+ unsigned int can_force_early_return : 1;
+ unsigned int can_get_owned_monitor_stack_depth_info : 1;
+ unsigned int can_get_constant_pool : 1;
+ unsigned int can_set_native_method_prefix : 1;
+ unsigned int can_retransform_classes : 1;
+ unsigned int can_retransform_any_class : 1;
+ unsigned int can_generate_resource_exhaustion_heap_events : 1;
+ unsigned int can_generate_resource_exhaustion_threads_events : 1;
+ unsigned int : 7;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+} jvmtiCapabilities;
+
+
+ /* Event Definitions */
+
+typedef void (JNICALL *jvmtiEventReserved)(void);
+
+
+typedef void (JNICALL *jvmtiEventBreakpoint)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventClassFileLoadHook)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jclass class_being_redefined,
+ jobject loader,
+ const char* name,
+ jobject protection_domain,
+ jint class_data_len,
+ const unsigned char* class_data,
+ jint* new_class_data_len,
+ unsigned char** new_class_data);
+
+typedef void (JNICALL *jvmtiEventClassLoad)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassPrepare)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jclass klass);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ jint code_size,
+ const void* code_addr,
+ jint map_length,
+ const jvmtiAddrLocationMap* map,
+ const void* compile_info);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
+ (jvmtiEnv *jvmti_env,
+ jmethodID method,
+ const void* code_addr);
+
+typedef void (JNICALL *jvmtiEventDataDumpRequest)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
+ (jvmtiEnv *jvmti_env,
+ const char* name,
+ const void* address,
+ jint length);
+
+typedef void (JNICALL *jvmtiEventException)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception,
+ jmethodID catch_method,
+ jlocation catch_location);
+
+typedef void (JNICALL *jvmtiEventExceptionCatch)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jobject exception);
+
+typedef void (JNICALL *jvmtiEventFieldAccess)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field);
+
+typedef void (JNICALL *jvmtiEventFieldModification)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location,
+ jclass field_klass,
+ jobject object,
+ jfieldID field,
+ char signature_type,
+ jvalue new_value);
+
+typedef void (JNICALL *jvmtiEventFramePop)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventMethodEntry)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method);
+
+typedef void (JNICALL *jvmtiEventMethodExit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jboolean was_popped_by_exception,
+ jvalue return_value);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorWait)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jlong timeout);
+
+typedef void (JNICALL *jvmtiEventMonitorWaited)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jboolean timed_out);
+
+typedef void (JNICALL *jvmtiEventNativeMethodBind)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ void* address,
+ void** new_address_ptr);
+
+typedef void (JNICALL *jvmtiEventObjectFree)
+ (jvmtiEnv *jvmti_env,
+ jlong tag);
+
+typedef void (JNICALL *jvmtiEventResourceExhausted)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jint flags,
+ const void* reserved,
+ const char* description);
+
+typedef void (JNICALL *jvmtiEventSingleStep)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventThreadEnd)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventThreadStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMDeath)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+typedef void (JNICALL *jvmtiEventVMInit)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMObjectAlloc)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env,
+ jthread thread,
+ jobject object,
+ jclass object_klass,
+ jlong size);
+
+typedef void (JNICALL *jvmtiEventVMStart)
+ (jvmtiEnv *jvmti_env,
+ JNIEnv* jni_env);
+
+ /* Event Callback Structure */
+
+typedef struct {
+ /* 50 : VM Initialization Event */
+ jvmtiEventVMInit VMInit;
+ /* 51 : VM Death Event */
+ jvmtiEventVMDeath VMDeath;
+ /* 52 : Thread Start */
+ jvmtiEventThreadStart ThreadStart;
+ /* 53 : Thread End */
+ jvmtiEventThreadEnd ThreadEnd;
+ /* 54 : Class File Load Hook */
+ jvmtiEventClassFileLoadHook ClassFileLoadHook;
+ /* 55 : Class Load */
+ jvmtiEventClassLoad ClassLoad;
+ /* 56 : Class Prepare */
+ jvmtiEventClassPrepare ClassPrepare;
+ /* 57 : VM Start Event */
+ jvmtiEventVMStart VMStart;
+ /* 58 : Exception */
+ jvmtiEventException Exception;
+ /* 59 : Exception Catch */
+ jvmtiEventExceptionCatch ExceptionCatch;
+ /* 60 : Single Step */
+ jvmtiEventSingleStep SingleStep;
+ /* 61 : Frame Pop */
+ jvmtiEventFramePop FramePop;
+ /* 62 : Breakpoint */
+ jvmtiEventBreakpoint Breakpoint;
+ /* 63 : Field Access */
+ jvmtiEventFieldAccess FieldAccess;
+ /* 64 : Field Modification */
+ jvmtiEventFieldModification FieldModification;
+ /* 65 : Method Entry */
+ jvmtiEventMethodEntry MethodEntry;
+ /* 66 : Method Exit */
+ jvmtiEventMethodExit MethodExit;
+ /* 67 : Native Method Bind */
+ jvmtiEventNativeMethodBind NativeMethodBind;
+ /* 68 : Compiled Method Load */
+ jvmtiEventCompiledMethodLoad CompiledMethodLoad;
+ /* 69 : Compiled Method Unload */
+ jvmtiEventCompiledMethodUnload CompiledMethodUnload;
+ /* 70 : Dynamic Code Generated */
+ jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
+ /* 71 : Data Dump Request */
+ jvmtiEventDataDumpRequest DataDumpRequest;
+ /* 72 */
+ jvmtiEventReserved reserved72;
+ /* 73 : Monitor Wait */
+ jvmtiEventMonitorWait MonitorWait;
+ /* 74 : Monitor Waited */
+ jvmtiEventMonitorWaited MonitorWaited;
+ /* 75 : Monitor Contended Enter */
+ jvmtiEventMonitorContendedEnter MonitorContendedEnter;
+ /* 76 : Monitor Contended Entered */
+ jvmtiEventMonitorContendedEntered MonitorContendedEntered;
+ /* 77 */
+ jvmtiEventReserved reserved77;
+ /* 78 */
+ jvmtiEventReserved reserved78;
+ /* 79 */
+ jvmtiEventReserved reserved79;
+ /* 80 : Resource Exhausted */
+ jvmtiEventResourceExhausted ResourceExhausted;
+ /* 81 : Garbage Collection Start */
+ jvmtiEventGarbageCollectionStart GarbageCollectionStart;
+ /* 82 : Garbage Collection Finish */
+ jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
+ /* 83 : Object Free */
+ jvmtiEventObjectFree ObjectFree;
+ /* 84 : VM Object Allocation */
+ jvmtiEventVMObjectAlloc VMObjectAlloc;
+} jvmtiEventCallbacks;
+
+
+ /* Function Interface */
+
+typedef struct jvmtiInterface_1_ {
+
+ /* 1 : RESERVED */
+ void *reserved1;
+
+ /* 2 : Set Event Notification Mode */
+ jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
+ jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...);
+
+ /* 3 : RESERVED */
+ void *reserved3;
+
+ /* 4 : Get All Threads */
+ jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
+ jint* threads_count_ptr,
+ jthread** threads_ptr);
+
+ /* 5 : Suspend Thread */
+ jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 6 : Resume Thread */
+ jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 7 : Stop Thread */
+ jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
+ jthread thread,
+ jobject exception);
+
+ /* 8 : Interrupt Thread */
+ jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 9 : Get Thread Info */
+ jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiThreadInfo* info_ptr);
+
+ /* 10 : Get Owned Monitor Info */
+ jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr);
+
+ /* 11 : Get Current Contended Monitor */
+ jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
+ jthread thread,
+ jobject* monitor_ptr);
+
+ /* 12 : Run Agent Thread */
+ jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
+ jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority);
+
+ /* 13 : Get Top Thread Groups */
+ jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 14 : Get Thread Group Info */
+ jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
+ jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr);
+
+ /* 15 : Get Thread Group Children */
+ jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
+ jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr);
+
+ /* 16 : Get Frame Count */
+ jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
+ jthread thread,
+ jint* count_ptr);
+
+ /* 17 : Get Thread State */
+ jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
+ jthread thread,
+ jint* thread_state_ptr);
+
+ /* 18 : Get Current Thread */
+ jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
+ jthread* thread_ptr);
+
+ /* 19 : Get Frame Location */
+ jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr);
+
+ /* 20 : Notify Frame Pop */
+ jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
+ jthread thread,
+ jint depth);
+
+ /* 21 : Get Local Variable - Object */
+ jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr);
+
+ /* 22 : Get Local Variable - Int */
+ jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr);
+
+ /* 23 : Get Local Variable - Long */
+ jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr);
+
+ /* 24 : Get Local Variable - Float */
+ jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr);
+
+ /* 25 : Get Local Variable - Double */
+ jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr);
+
+ /* 26 : Set Local Variable - Object */
+ jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject value);
+
+ /* 27 : Set Local Variable - Int */
+ jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint value);
+
+ /* 28 : Set Local Variable - Long */
+ jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong value);
+
+ /* 29 : Set Local Variable - Float */
+ jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value);
+
+ /* 30 : Set Local Variable - Double */
+ jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value);
+
+ /* 31 : Create Raw Monitor */
+ jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
+ const char* name,
+ jrawMonitorID* monitor_ptr);
+
+ /* 32 : Destroy Raw Monitor */
+ jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 33 : Raw Monitor Enter */
+ jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 34 : Raw Monitor Exit */
+ jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 35 : Raw Monitor Wait */
+ jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
+ jrawMonitorID monitor,
+ jlong millis);
+
+ /* 36 : Raw Monitor Notify */
+ jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 37 : Raw Monitor Notify All */
+ jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
+ jrawMonitorID monitor);
+
+ /* 38 : Set Breakpoint */
+ jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 39 : Clear Breakpoint */
+ jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation location);
+
+ /* 40 : RESERVED */
+ void *reserved40;
+
+ /* 41 : Set Field Access Watch */
+ jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 42 : Clear Field Access Watch */
+ jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 43 : Set Field Modification Watch */
+ jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 44 : Clear Field Modification Watch */
+ jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field);
+
+ /* 45 : Is Modifiable Class */
+ jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_modifiable_class_ptr);
+
+ /* 46 : Allocate */
+ jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
+ jlong size,
+ unsigned char** mem_ptr);
+
+ /* 47 : Deallocate */
+ jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
+ unsigned char* mem);
+
+ /* 48 : Get Class Signature */
+ jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
+ jclass klass,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 49 : Get Class Status */
+ jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
+ jclass klass,
+ jint* status_ptr);
+
+ /* 50 : Get Source File Name */
+ jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
+ jclass klass,
+ char** source_name_ptr);
+
+ /* 51 : Get Class Modifiers */
+ jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jint* modifiers_ptr);
+
+ /* 52 : Get Class Methods */
+ jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
+ jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr);
+
+ /* 53 : Get Class Fields */
+ jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
+ jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr);
+
+ /* 54 : Get Implemented Interfaces */
+ jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
+ jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr);
+
+ /* 55 : Is Interface */
+ jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_interface_ptr);
+
+ /* 56 : Is Array Class */
+ jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
+ jclass klass,
+ jboolean* is_array_class_ptr);
+
+ /* 57 : Get Class Loader */
+ jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
+ jclass klass,
+ jobject* classloader_ptr);
+
+ /* 58 : Get Object Hash Code */
+ jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
+ jobject object,
+ jint* hash_code_ptr);
+
+ /* 59 : Get Object Monitor Usage */
+ jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
+ jobject object,
+ jvmtiMonitorUsage* info_ptr);
+
+ /* 60 : Get Field Name (and Signature) */
+ jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 61 : Get Field Declaring Class */
+ jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr);
+
+ /* 62 : Get Field Modifiers */
+ jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr);
+
+ /* 63 : Is Field Synthetic */
+ jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
+ jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr);
+
+ /* 64 : Get Method Name (and Signature) */
+ jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
+ jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr);
+
+ /* 65 : Get Method Declaring Class */
+ jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
+ jmethodID method,
+ jclass* declaring_class_ptr);
+
+ /* 66 : Get Method Modifiers */
+ jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
+ jmethodID method,
+ jint* modifiers_ptr);
+
+ /* 67 : RESERVED */
+ void *reserved67;
+
+ /* 68 : Get Max Locals */
+ jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
+ jmethodID method,
+ jint* max_ptr);
+
+ /* 69 : Get Arguments Size */
+ jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
+ jmethodID method,
+ jint* size_ptr);
+
+ /* 70 : Get Line Number Table */
+ jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr);
+
+ /* 71 : Get Method Location */
+ jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
+ jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr);
+
+ /* 72 : Get Local Variable Table */
+ jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
+ jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr);
+
+ /* 73 : Set Native Method Prefix */
+ jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
+ const char* prefix);
+
+ /* 74 : Set Native Method Prefixes */
+ jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
+ jint prefix_count,
+ char** prefixes);
+
+ /* 75 : Get Bytecodes */
+ jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
+ jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr);
+
+ /* 76 : Is Method Native */
+ jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_native_ptr);
+
+ /* 77 : Is Method Synthetic */
+ jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_synthetic_ptr);
+
+ /* 78 : Get Loaded Classes */
+ jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 79 : Get Classloader Classes */
+ jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
+ jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr);
+
+ /* 80 : Pop Frame */
+ jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 81 : Force Early Return - Object */
+ jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
+ jthread thread,
+ jobject value);
+
+ /* 82 : Force Early Return - Int */
+ jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
+ jthread thread,
+ jint value);
+
+ /* 83 : Force Early Return - Long */
+ jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
+ jthread thread,
+ jlong value);
+
+ /* 84 : Force Early Return - Float */
+ jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
+ jthread thread,
+ jfloat value);
+
+ /* 85 : Force Early Return - Double */
+ jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
+ jthread thread,
+ jdouble value);
+
+ /* 86 : Force Early Return - Void */
+ jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
+ jthread thread);
+
+ /* 87 : Redefine Classes */
+ jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jvmtiClassDefinition* class_definitions);
+
+ /* 88 : Get Version Number */
+ jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
+ jint* version_ptr);
+
+ /* 89 : Get Capabilities */
+ jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 90 : Get Source Debug Extension */
+ jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
+ jclass klass,
+ char** source_debug_extension_ptr);
+
+ /* 91 : Is Method Obsolete */
+ jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
+ jmethodID method,
+ jboolean* is_obsolete_ptr);
+
+ /* 92 : Suspend Thread List */
+ jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 93 : Resume Thread List */
+ jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
+ jint request_count,
+ const jthread* request_list,
+ jvmtiError* results);
+
+ /* 94 : RESERVED */
+ void *reserved94;
+
+ /* 95 : RESERVED */
+ void *reserved95;
+
+ /* 96 : RESERVED */
+ void *reserved96;
+
+ /* 97 : RESERVED */
+ void *reserved97;
+
+ /* 98 : RESERVED */
+ void *reserved98;
+
+ /* 99 : RESERVED */
+ void *reserved99;
+
+ /* 100 : Get All Stack Traces */
+ jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr);
+
+ /* 101 : Get Thread List Stack Traces */
+ jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
+ jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr);
+
+ /* 102 : Get Thread Local Storage */
+ jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ void** data_ptr);
+
+ /* 103 : Set Thread Local Storage */
+ jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
+ jthread thread,
+ const void* data);
+
+ /* 104 : Get Stack Trace */
+ jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
+ jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr);
+
+ /* 105 : RESERVED */
+ void *reserved105;
+
+ /* 106 : Get Tag */
+ jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong* tag_ptr);
+
+ /* 107 : Set Tag */
+ jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
+ jobject object,
+ jlong tag);
+
+ /* 108 : Force Garbage Collection */
+ jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
+
+ /* 109 : Iterate Over Objects Reachable From Object */
+ jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
+ jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data);
+
+ /* 110 : Iterate Over Reachable Objects */
+ jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
+ jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data);
+
+ /* 111 : Iterate Over Heap */
+ jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 112 : Iterate Over Instances Of Class */
+ jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
+ jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data);
+
+ /* 113 : RESERVED */
+ void *reserved113;
+
+ /* 114 : Get Objects With Tags */
+ jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
+ jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr);
+
+ /* 115 : Follow References */
+ jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 116 : Iterate Through Heap */
+ jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
+ jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data);
+
+ /* 117 : RESERVED */
+ void *reserved117;
+
+ /* 118 : RESERVED */
+ void *reserved118;
+
+ /* 119 : RESERVED */
+ void *reserved119;
+
+ /* 120 : Set JNI Function Table */
+ jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
+ const jniNativeInterface* function_table);
+
+ /* 121 : Get JNI Function Table */
+ jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
+ jniNativeInterface** function_table);
+
+ /* 122 : Set Event Callbacks */
+ jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
+ const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks);
+
+ /* 123 : Generate Events */
+ jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
+ jvmtiEvent event_type);
+
+ /* 124 : Get Extension Functions */
+ jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions);
+
+ /* 125 : Get Extension Events */
+ jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
+ jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions);
+
+ /* 126 : Set Extension Event Callback */
+ jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
+ jint extension_event_index,
+ jvmtiExtensionEvent callback);
+
+ /* 127 : Dispose Environment */
+ jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
+
+ /* 128 : Get Error Name */
+ jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
+ jvmtiError error,
+ char** name_ptr);
+
+ /* 129 : Get JLocation Format */
+ jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
+ jvmtiJlocationFormat* format_ptr);
+
+ /* 130 : Get System Properties */
+ jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
+ jint* count_ptr,
+ char*** property_ptr);
+
+ /* 131 : Get System Property */
+ jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ char** value_ptr);
+
+ /* 132 : Set System Property */
+ jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
+ const char* property,
+ const char* value);
+
+ /* 133 : Get Phase */
+ jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
+ jvmtiPhase* phase_ptr);
+
+ /* 134 : Get Current Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 135 : Get Current Thread CPU Time */
+ jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 136 : Get Thread CPU Timer Information */
+ jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 137 : Get Thread CPU Time */
+ jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
+ jthread thread,
+ jlong* nanos_ptr);
+
+ /* 138 : Get Timer Information */
+ jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
+ jvmtiTimerInfo* info_ptr);
+
+ /* 139 : Get Time */
+ jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
+ jlong* nanos_ptr);
+
+ /* 140 : Get Potential Capabilities */
+ jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
+ jvmtiCapabilities* capabilities_ptr);
+
+ /* 141 : RESERVED */
+ void *reserved141;
+
+ /* 142 : Add Capabilities */
+ jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 143 : Relinquish Capabilities */
+ jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
+ const jvmtiCapabilities* capabilities_ptr);
+
+ /* 144 : Get Available Processors */
+ jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
+ jint* processor_count_ptr);
+
+ /* 145 : Get Class Version Numbers */
+ jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
+ jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr);
+
+ /* 146 : Get Constant Pool */
+ jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
+ jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr);
+
+ /* 147 : Get Environment Local Storage */
+ jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
+ void** data_ptr);
+
+ /* 148 : Set Environment Local Storage */
+ jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
+ const void* data);
+
+ /* 149 : Add To Bootstrap Class Loader Search */
+ jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 150 : Set Verbose Flag */
+ jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
+ jvmtiVerboseFlag flag,
+ jboolean value);
+
+ /* 151 : Add To System Class Loader Search */
+ jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
+ const char* segment);
+
+ /* 152 : Retransform Classes */
+ jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
+ jint class_count,
+ const jclass* classes);
+
+ /* 153 : Get Owned Monitor Stack Depth Info */
+ jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
+ jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr);
+
+ /* 154 : Get Object Size */
+ jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
+ jobject object,
+ jlong* size_ptr);
+
+ /* 155 : Get Local Instance */
+ jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jobject* value_ptr);
+
+} jvmtiInterface_1;
+
+struct _jvmtiEnv {
+ const struct jvmtiInterface_1_ *functions;
+#ifdef __cplusplus
+
+
+ jvmtiError Allocate(jlong size,
+ unsigned char** mem_ptr) {
+ return functions->Allocate(this, size, mem_ptr);
+ }
+
+ jvmtiError Deallocate(unsigned char* mem) {
+ return functions->Deallocate(this, mem);
+ }
+
+ jvmtiError GetThreadState(jthread thread,
+ jint* thread_state_ptr) {
+ return functions->GetThreadState(this, thread, thread_state_ptr);
+ }
+
+ jvmtiError GetCurrentThread(jthread* thread_ptr) {
+ return functions->GetCurrentThread(this, thread_ptr);
+ }
+
+ jvmtiError GetAllThreads(jint* threads_count_ptr,
+ jthread** threads_ptr) {
+ return functions->GetAllThreads(this, threads_count_ptr, threads_ptr);
+ }
+
+ jvmtiError SuspendThread(jthread thread) {
+ return functions->SuspendThread(this, thread);
+ }
+
+ jvmtiError SuspendThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->SuspendThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError ResumeThread(jthread thread) {
+ return functions->ResumeThread(this, thread);
+ }
+
+ jvmtiError ResumeThreadList(jint request_count,
+ const jthread* request_list,
+ jvmtiError* results) {
+ return functions->ResumeThreadList(this, request_count, request_list, results);
+ }
+
+ jvmtiError StopThread(jthread thread,
+ jobject exception) {
+ return functions->StopThread(this, thread, exception);
+ }
+
+ jvmtiError InterruptThread(jthread thread) {
+ return functions->InterruptThread(this, thread);
+ }
+
+ jvmtiError GetThreadInfo(jthread thread,
+ jvmtiThreadInfo* info_ptr) {
+ return functions->GetThreadInfo(this, thread, info_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorInfo(jthread thread,
+ jint* owned_monitor_count_ptr,
+ jobject** owned_monitors_ptr) {
+ return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr);
+ }
+
+ jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread,
+ jint* monitor_info_count_ptr,
+ jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
+ return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr);
+ }
+
+ jvmtiError GetCurrentContendedMonitor(jthread thread,
+ jobject* monitor_ptr) {
+ return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr);
+ }
+
+ jvmtiError RunAgentThread(jthread thread,
+ jvmtiStartFunction proc,
+ const void* arg,
+ jint priority) {
+ return functions->RunAgentThread(this, thread, proc, arg, priority);
+ }
+
+ jvmtiError SetThreadLocalStorage(jthread thread,
+ const void* data) {
+ return functions->SetThreadLocalStorage(this, thread, data);
+ }
+
+ jvmtiError GetThreadLocalStorage(jthread thread,
+ void** data_ptr) {
+ return functions->GetThreadLocalStorage(this, thread, data_ptr);
+ }
+
+ jvmtiError GetTopThreadGroups(jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetThreadGroupInfo(jthreadGroup group,
+ jvmtiThreadGroupInfo* info_ptr) {
+ return functions->GetThreadGroupInfo(this, group, info_ptr);
+ }
+
+ jvmtiError GetThreadGroupChildren(jthreadGroup group,
+ jint* thread_count_ptr,
+ jthread** threads_ptr,
+ jint* group_count_ptr,
+ jthreadGroup** groups_ptr) {
+ return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr);
+ }
+
+ jvmtiError GetStackTrace(jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo* frame_buffer,
+ jint* count_ptr) {
+ return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr);
+ }
+
+ jvmtiError GetAllStackTraces(jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr,
+ jint* thread_count_ptr) {
+ return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr);
+ }
+
+ jvmtiError GetThreadListStackTraces(jint thread_count,
+ const jthread* thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo** stack_info_ptr) {
+ return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr);
+ }
+
+ jvmtiError GetFrameCount(jthread thread,
+ jint* count_ptr) {
+ return functions->GetFrameCount(this, thread, count_ptr);
+ }
+
+ jvmtiError PopFrame(jthread thread) {
+ return functions->PopFrame(this, thread);
+ }
+
+ jvmtiError GetFrameLocation(jthread thread,
+ jint depth,
+ jmethodID* method_ptr,
+ jlocation* location_ptr) {
+ return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr);
+ }
+
+ jvmtiError NotifyFramePop(jthread thread,
+ jint depth) {
+ return functions->NotifyFramePop(this, thread, depth);
+ }
+
+ jvmtiError ForceEarlyReturnObject(jthread thread,
+ jobject value) {
+ return functions->ForceEarlyReturnObject(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnInt(jthread thread,
+ jint value) {
+ return functions->ForceEarlyReturnInt(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnLong(jthread thread,
+ jlong value) {
+ return functions->ForceEarlyReturnLong(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnFloat(jthread thread,
+ jfloat value) {
+ return functions->ForceEarlyReturnFloat(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnDouble(jthread thread,
+ jdouble value) {
+ return functions->ForceEarlyReturnDouble(this, thread, value);
+ }
+
+ jvmtiError ForceEarlyReturnVoid(jthread thread) {
+ return functions->ForceEarlyReturnVoid(this, thread);
+ }
+
+ jvmtiError FollowReferences(jint heap_filter,
+ jclass klass,
+ jobject initial_object,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data);
+ }
+
+ jvmtiError IterateThroughHeap(jint heap_filter,
+ jclass klass,
+ const jvmtiHeapCallbacks* callbacks,
+ const void* user_data) {
+ return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data);
+ }
+
+ jvmtiError GetTag(jobject object,
+ jlong* tag_ptr) {
+ return functions->GetTag(this, object, tag_ptr);
+ }
+
+ jvmtiError SetTag(jobject object,
+ jlong tag) {
+ return functions->SetTag(this, object, tag);
+ }
+
+ jvmtiError GetObjectsWithTags(jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr) {
+ return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr);
+ }
+
+ jvmtiError ForceGarbageCollection() {
+ return functions->ForceGarbageCollection(this);
+ }
+
+ jvmtiError IterateOverObjectsReachableFromObject(jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ const void* user_data) {
+ return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data);
+ }
+
+ jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ const void* user_data) {
+ return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
+ }
+
+ jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError IterateOverInstancesOfClass(jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ const void* user_data) {
+ return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data);
+ }
+
+ jvmtiError GetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject* value_ptr) {
+ return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalInstance(jthread thread,
+ jint depth,
+ jobject* value_ptr) {
+ return functions->GetLocalInstance(this, thread, depth, value_ptr);
+ }
+
+ jvmtiError GetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint* value_ptr) {
+ return functions->GetLocalInt(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong* value_ptr) {
+ return functions->GetLocalLong(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat* value_ptr) {
+ return functions->GetLocalFloat(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError GetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble* value_ptr) {
+ return functions->GetLocalDouble(this, thread, depth, slot, value_ptr);
+ }
+
+ jvmtiError SetLocalObject(jthread thread,
+ jint depth,
+ jint slot,
+ jobject value) {
+ return functions->SetLocalObject(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalInt(jthread thread,
+ jint depth,
+ jint slot,
+ jint value) {
+ return functions->SetLocalInt(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalLong(jthread thread,
+ jint depth,
+ jint slot,
+ jlong value) {
+ return functions->SetLocalLong(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalFloat(jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value) {
+ return functions->SetLocalFloat(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetLocalDouble(jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value) {
+ return functions->SetLocalDouble(this, thread, depth, slot, value);
+ }
+
+ jvmtiError SetBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->SetBreakpoint(this, method, location);
+ }
+
+ jvmtiError ClearBreakpoint(jmethodID method,
+ jlocation location) {
+ return functions->ClearBreakpoint(this, method, location);
+ }
+
+ jvmtiError SetFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldAccessWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldAccessWatch(this, klass, field);
+ }
+
+ jvmtiError SetFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->SetFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError ClearFieldModificationWatch(jclass klass,
+ jfieldID field) {
+ return functions->ClearFieldModificationWatch(this, klass, field);
+ }
+
+ jvmtiError GetLoadedClasses(jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassLoaderClasses(jobject initiating_loader,
+ jint* class_count_ptr,
+ jclass** classes_ptr) {
+ return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError GetClassSignature(jclass klass,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetClassStatus(jclass klass,
+ jint* status_ptr) {
+ return functions->GetClassStatus(this, klass, status_ptr);
+ }
+
+ jvmtiError GetSourceFileName(jclass klass,
+ char** source_name_ptr) {
+ return functions->GetSourceFileName(this, klass, source_name_ptr);
+ }
+
+ jvmtiError GetClassModifiers(jclass klass,
+ jint* modifiers_ptr) {
+ return functions->GetClassModifiers(this, klass, modifiers_ptr);
+ }
+
+ jvmtiError GetClassMethods(jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr) {
+ return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr);
+ }
+
+ jvmtiError GetClassFields(jclass klass,
+ jint* field_count_ptr,
+ jfieldID** fields_ptr) {
+ return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr);
+ }
+
+ jvmtiError GetImplementedInterfaces(jclass klass,
+ jint* interface_count_ptr,
+ jclass** interfaces_ptr) {
+ return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr);
+ }
+
+ jvmtiError GetClassVersionNumbers(jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr) {
+ return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr);
+ }
+
+ jvmtiError GetConstantPool(jclass klass,
+ jint* constant_pool_count_ptr,
+ jint* constant_pool_byte_count_ptr,
+ unsigned char** constant_pool_bytes_ptr) {
+ return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr);
+ }
+
+ jvmtiError IsInterface(jclass klass,
+ jboolean* is_interface_ptr) {
+ return functions->IsInterface(this, klass, is_interface_ptr);
+ }
+
+ jvmtiError IsArrayClass(jclass klass,
+ jboolean* is_array_class_ptr) {
+ return functions->IsArrayClass(this, klass, is_array_class_ptr);
+ }
+
+ jvmtiError IsModifiableClass(jclass klass,
+ jboolean* is_modifiable_class_ptr) {
+ return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr);
+ }
+
+ jvmtiError GetClassLoader(jclass klass,
+ jobject* classloader_ptr) {
+ return functions->GetClassLoader(this, klass, classloader_ptr);
+ }
+
+ jvmtiError GetSourceDebugExtension(jclass klass,
+ char** source_debug_extension_ptr) {
+ return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr);
+ }
+
+ jvmtiError RetransformClasses(jint class_count,
+ const jclass* classes) {
+ return functions->RetransformClasses(this, class_count, classes);
+ }
+
+ jvmtiError RedefineClasses(jint class_count,
+ const jvmtiClassDefinition* class_definitions) {
+ return functions->RedefineClasses(this, class_count, class_definitions);
+ }
+
+ jvmtiError GetObjectSize(jobject object,
+ jlong* size_ptr) {
+ return functions->GetObjectSize(this, object, size_ptr);
+ }
+
+ jvmtiError GetObjectHashCode(jobject object,
+ jint* hash_code_ptr) {
+ return functions->GetObjectHashCode(this, object, hash_code_ptr);
+ }
+
+ jvmtiError GetObjectMonitorUsage(jobject object,
+ jvmtiMonitorUsage* info_ptr) {
+ return functions->GetObjectMonitorUsage(this, object, info_ptr);
+ }
+
+ jvmtiError GetFieldName(jclass klass,
+ jfieldID field,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetFieldDeclaringClass(jclass klass,
+ jfieldID field,
+ jclass* declaring_class_ptr) {
+ return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr);
+ }
+
+ jvmtiError GetFieldModifiers(jclass klass,
+ jfieldID field,
+ jint* modifiers_ptr) {
+ return functions->GetFieldModifiers(this, klass, field, modifiers_ptr);
+ }
+
+ jvmtiError IsFieldSynthetic(jclass klass,
+ jfieldID field,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr);
+ }
+
+ jvmtiError GetMethodName(jmethodID method,
+ char** name_ptr,
+ char** signature_ptr,
+ char** generic_ptr) {
+ return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetMethodDeclaringClass(jmethodID method,
+ jclass* declaring_class_ptr) {
+ return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr);
+ }
+
+ jvmtiError GetMethodModifiers(jmethodID method,
+ jint* modifiers_ptr) {
+ return functions->GetMethodModifiers(this, method, modifiers_ptr);
+ }
+
+ jvmtiError GetMaxLocals(jmethodID method,
+ jint* max_ptr) {
+ return functions->GetMaxLocals(this, method, max_ptr);
+ }
+
+ jvmtiError GetArgumentsSize(jmethodID method,
+ jint* size_ptr) {
+ return functions->GetArgumentsSize(this, method, size_ptr);
+ }
+
+ jvmtiError GetLineNumberTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLineNumberEntry** table_ptr) {
+ return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetMethodLocation(jmethodID method,
+ jlocation* start_location_ptr,
+ jlocation* end_location_ptr) {
+ return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr);
+ }
+
+ jvmtiError GetLocalVariableTable(jmethodID method,
+ jint* entry_count_ptr,
+ jvmtiLocalVariableEntry** table_ptr) {
+ return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr);
+ }
+
+ jvmtiError GetBytecodes(jmethodID method,
+ jint* bytecode_count_ptr,
+ unsigned char** bytecodes_ptr) {
+ return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr);
+ }
+
+ jvmtiError IsMethodNative(jmethodID method,
+ jboolean* is_native_ptr) {
+ return functions->IsMethodNative(this, method, is_native_ptr);
+ }
+
+ jvmtiError IsMethodSynthetic(jmethodID method,
+ jboolean* is_synthetic_ptr) {
+ return functions->IsMethodSynthetic(this, method, is_synthetic_ptr);
+ }
+
+ jvmtiError IsMethodObsolete(jmethodID method,
+ jboolean* is_obsolete_ptr) {
+ return functions->IsMethodObsolete(this, method, is_obsolete_ptr);
+ }
+
+ jvmtiError SetNativeMethodPrefix(const char* prefix) {
+ return functions->SetNativeMethodPrefix(this, prefix);
+ }
+
+ jvmtiError SetNativeMethodPrefixes(jint prefix_count,
+ char** prefixes) {
+ return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes);
+ }
+
+ jvmtiError CreateRawMonitor(const char* name,
+ jrawMonitorID* monitor_ptr) {
+ return functions->CreateRawMonitor(this, name, monitor_ptr);
+ }
+
+ jvmtiError DestroyRawMonitor(jrawMonitorID monitor) {
+ return functions->DestroyRawMonitor(this, monitor);
+ }
+
+ jvmtiError RawMonitorEnter(jrawMonitorID monitor) {
+ return functions->RawMonitorEnter(this, monitor);
+ }
+
+ jvmtiError RawMonitorExit(jrawMonitorID monitor) {
+ return functions->RawMonitorExit(this, monitor);
+ }
+
+ jvmtiError RawMonitorWait(jrawMonitorID monitor,
+ jlong millis) {
+ return functions->RawMonitorWait(this, monitor, millis);
+ }
+
+ jvmtiError RawMonitorNotify(jrawMonitorID monitor) {
+ return functions->RawMonitorNotify(this, monitor);
+ }
+
+ jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) {
+ return functions->RawMonitorNotifyAll(this, monitor);
+ }
+
+ jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) {
+ return functions->SetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) {
+ return functions->GetJNIFunctionTable(this, function_table);
+ }
+
+ jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks,
+ jint size_of_callbacks) {
+ return functions->SetEventCallbacks(this, callbacks, size_of_callbacks);
+ }
+
+ jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread,
+ ...) {
+ return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
+ }
+
+ jvmtiError GenerateEvents(jvmtiEvent event_type) {
+ return functions->GenerateEvents(this, event_type);
+ }
+
+ jvmtiError GetExtensionFunctions(jint* extension_count_ptr,
+ jvmtiExtensionFunctionInfo** extensions) {
+ return functions->GetExtensionFunctions(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError GetExtensionEvents(jint* extension_count_ptr,
+ jvmtiExtensionEventInfo** extensions) {
+ return functions->GetExtensionEvents(this, extension_count_ptr, extensions);
+ }
+
+ jvmtiError SetExtensionEventCallback(jint extension_event_index,
+ jvmtiExtensionEvent callback) {
+ return functions->SetExtensionEventCallback(this, extension_event_index, callback);
+ }
+
+ jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetPotentialCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->AddCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
+ return functions->RelinquishCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
+ return functions->GetCapabilities(this, capabilities_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) {
+ return functions->GetCurrentThreadCpuTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetThreadCpuTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetThreadCpuTime(jthread thread,
+ jlong* nanos_ptr) {
+ return functions->GetThreadCpuTime(this, thread, nanos_ptr);
+ }
+
+ jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) {
+ return functions->GetTimerInfo(this, info_ptr);
+ }
+
+ jvmtiError GetTime(jlong* nanos_ptr) {
+ return functions->GetTime(this, nanos_ptr);
+ }
+
+ jvmtiError GetAvailableProcessors(jint* processor_count_ptr) {
+ return functions->GetAvailableProcessors(this, processor_count_ptr);
+ }
+
+ jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) {
+ return functions->AddToBootstrapClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError AddToSystemClassLoaderSearch(const char* segment) {
+ return functions->AddToSystemClassLoaderSearch(this, segment);
+ }
+
+ jvmtiError GetSystemProperties(jint* count_ptr,
+ char*** property_ptr) {
+ return functions->GetSystemProperties(this, count_ptr, property_ptr);
+ }
+
+ jvmtiError GetSystemProperty(const char* property,
+ char** value_ptr) {
+ return functions->GetSystemProperty(this, property, value_ptr);
+ }
+
+ jvmtiError SetSystemProperty(const char* property,
+ const char* value) {
+ return functions->SetSystemProperty(this, property, value);
+ }
+
+ jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
+ return functions->GetPhase(this, phase_ptr);
+ }
+
+ jvmtiError DisposeEnvironment() {
+ return functions->DisposeEnvironment(this);
+ }
+
+ jvmtiError SetEnvironmentLocalStorage(const void* data) {
+ return functions->SetEnvironmentLocalStorage(this, data);
+ }
+
+ jvmtiError GetEnvironmentLocalStorage(void** data_ptr) {
+ return functions->GetEnvironmentLocalStorage(this, data_ptr);
+ }
+
+ jvmtiError GetVersionNumber(jint* version_ptr) {
+ return functions->GetVersionNumber(this, version_ptr);
+ }
+
+ jvmtiError GetErrorName(jvmtiError error,
+ char** name_ptr) {
+ return functions->GetErrorName(this, error, name_ptr);
+ }
+
+ jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag,
+ jboolean value) {
+ return functions->SetVerboseFlag(this, flag, value);
+ }
+
+ jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
+ return functions->GetJLocationFormat(this, format_ptr);
+ }
+
+#endif /* __cplusplus */
+};
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVA_JVMTI_H_ */ \ No newline at end of file
diff --git a/demos/java/jni/gs_jni/include/jvmticmlr.h b/demos/java/jni/gs_jni/include/jvmticmlr.h
new file mode 100644
index 00000000..a9c88f36
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/jvmticmlr.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * This header file defines the data structures sent by the VM
+ * through the JVMTI CompiledMethodLoad callback function via the
+ * "void * compile_info" parameter. The memory pointed to by the
+ * compile_info parameter may not be referenced after returning from
+ * the CompiledMethodLoad callback. These are VM implementation
+ * specific data structures that may evolve in future releases. A
+ * JVMTI agent should interpret a non-NULL compile_info as a pointer
+ * to a region of memory containing a list of records. In a typical
+ * usage scenario, a JVMTI agent would cast each record to a
+ * jvmtiCompiledMethodLoadRecordHeader, a struct that represents
+ * arbitrary information. This struct contains a kind field to indicate
+ * the kind of information being passed, and a pointer to the next
+ * record. If the kind field indicates inlining information, then the
+ * agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord.
+ * This record contains an array of PCStackInfo structs, which indicate
+ * for every pc address what are the methods on the invocation stack.
+ * The "methods" and "bcis" fields in each PCStackInfo struct specify a
+ * 1-1 mapping between these inlined methods and their bytecode indices.
+ * This can be used to derive the proper source lines of the inlined
+ * methods.
+ */
+
+#ifndef _JVMTI_CMLR_H_
+#define _JVMTI_CMLR_H_
+
+enum {
+ JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001,
+ JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000,
+
+ JVMTI_CMLR_MAJOR_VERSION = 0x00000001,
+ JVMTI_CMLR_MINOR_VERSION = 0x00000000
+
+ /*
+ * This comment is for the "JDK import from HotSpot" sanity check:
+ * version: 1.0.0
+ */
+};
+
+typedef enum {
+ JVMTI_CMLR_DUMMY = 1,
+ JVMTI_CMLR_INLINE_INFO = 2
+} jvmtiCMLRKind;
+
+/*
+ * Record that represents arbitrary information passed through JVMTI
+ * CompiledMethodLoadEvent void pointer.
+ */
+typedef struct _jvmtiCompiledMethodLoadRecordHeader {
+ jvmtiCMLRKind kind; /* id for the kind of info passed in the record */
+ jint majorinfoversion; /* major and minor info version values. Init'ed */
+ jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */
+
+ struct _jvmtiCompiledMethodLoadRecordHeader* next;
+} jvmtiCompiledMethodLoadRecordHeader;
+
+/*
+ * Record that gives information about the methods on the compile-time
+ * stack at a specific pc address of a compiled method. Each element in
+ * the methods array maps to same element in the bcis array.
+ */
+typedef struct _PCStackInfo {
+ void* pc; /* the pc address for this compiled method */
+ jint numstackframes; /* number of methods on the stack */
+ jmethodID* methods; /* array of numstackframes method ids */
+ jint* bcis; /* array of numstackframes bytecode indices */
+} PCStackInfo;
+
+/*
+ * Record that contains inlining information for each pc address of
+ * an nmethod.
+ */
+typedef struct _jvmtiCompiledMethodLoadInlineRecord {
+ jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
+ jint numpcs; /* number of pc descriptors in this nmethod */
+ PCStackInfo* pcinfo; /* array of numpcs pc descriptors */
+} jvmtiCompiledMethodLoadInlineRecord;
+
+/*
+ * Dummy record used to test that we can pass records with different
+ * information through the void pointer provided that they can be cast
+ * to a jvmtiCompiledMethodLoadRecordHeader.
+ */
+
+typedef struct _jvmtiCompiledMethodLoadDummyRecord {
+ jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */
+ char message[50];
+} jvmtiCompiledMethodLoadDummyRecord;
+
+#endif
diff --git a/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCallbacks.h b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCallbacks.h
new file mode 100644
index 00000000..df5035b8
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCallbacks.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * AccessBridgeCallbacks.h 1.17 05/03/21
+ */
+
+/*
+ * Header file defining callback typedefs for Windows routines
+ * which are called from Java (responding to events, etc.).
+ */
+
+#ifndef __AccessBridgeCallbacks_H__
+#define __AccessBridgeCallbacks_H__
+
+#include <jni.h>
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*AccessBridge_PropertyChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *property, wchar_t *oldValue, wchar_t *newValue);
+
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+
+typedef void (*AccessBridge_FocusGainedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_FocusLostFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_CaretUpdateFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MouseClickedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseEnteredFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseExitedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MousePressedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseReleasedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuDeselectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuSelectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeInvisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeVisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_PropertyNameChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldName, wchar_t *newName);
+typedef void (*AccessBridge_PropertyDescriptionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldDescription, wchar_t *newDescription);
+typedef void (*AccessBridge_PropertyStateChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldState, wchar_t *newState);
+typedef void (*AccessBridge_PropertyValueChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldValue, wchar_t *newValue);
+typedef void (*AccessBridge_PropertySelectionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyTextChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyCaretChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ int oldPosition, int newPosition);
+typedef void (*AccessBridge_PropertyVisibleDataChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyChildChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ JOBJECT64 oldChild, JOBJECT64 newChild);
+typedef void (*AccessBridge_PropertyActiveDescendentChangeFP) (long vmID, JOBJECT64 event,
+ JOBJECT64 source,
+ JOBJECT64 oldActiveDescendent,
+ JOBJECT64 newActiveDescendent);
+
+typedef void (*AccessBridge_PropertyTableModelChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 src,
+ wchar_t *oldValue, wchar_t *newValue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.c b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.c
new file mode 100644
index 00000000..36866481
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * @(#)AccessBridgeCalls.c 1.25 05/08/22
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+
+#include <windows.h>
+#include <jni.h>
+
+
+//#define ACCESSBRIDGE_32
+//#define ACCESSBRIDGE_64
+
+#include "AccessBridgeCalls.h"
+#include "AccessBridgeDebug.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ HINSTANCE theAccessBridgeInstance;
+ AccessBridgeFPs theAccessBridge;
+
+ BOOL theAccessBridgeInitializedFlag = FALSE;
+
+#define LOAD_FP(result, type, name) \
+ PrintDebugString("LOAD_FP loading: %s ...", name); \
+ if ((theAccessBridge.result = \
+ (type) GetProcAddress(theAccessBridgeInstance, name)) == (type) 0) { \
+ PrintDebugString("LOAD_FP failed: %s", name); \
+ return FALSE; \
+ }
+
+ BOOL initializeAccessBridge() {
+
+#ifdef ACCESSBRIDGE_ARCH_32 // For 32bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-32");
+#else
+#ifdef ACCESSBRIDGE_ARCH_64 // For 64bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-64");
+#else // legacy
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE");
+#endif
+#endif
+ if (theAccessBridgeInstance != 0) {
+ LOAD_FP(Windows_run, Windows_runFP, "Windows_run");
+
+ LOAD_FP(SetJavaShutdown, SetJavaShutdownFP, "setJavaShutdownFP");
+ LOAD_FP(SetFocusGained, SetFocusGainedFP, "setFocusGainedFP");
+ LOAD_FP(SetFocusLost, SetFocusLostFP, "setFocusLostFP");
+
+ LOAD_FP(SetCaretUpdate, SetCaretUpdateFP, "setCaretUpdateFP");
+
+ LOAD_FP(SetMouseClicked, SetMouseClickedFP, "setMouseClickedFP");
+ LOAD_FP(SetMouseEntered, SetMouseEnteredFP, "setMouseEnteredFP");
+ LOAD_FP(SetMouseExited, SetMouseExitedFP, "setMouseExitedFP");
+ LOAD_FP(SetMousePressed, SetMousePressedFP, "setMousePressedFP");
+ LOAD_FP(SetMouseReleased, SetMouseReleasedFP, "setMouseReleasedFP");
+
+ LOAD_FP(SetMenuCanceled, SetMenuCanceledFP, "setMenuCanceledFP");
+ LOAD_FP(SetMenuDeselected, SetMenuDeselectedFP, "setMenuDeselectedFP");
+ LOAD_FP(SetMenuSelected, SetMenuSelectedFP, "setMenuSelectedFP");
+ LOAD_FP(SetPopupMenuCanceled, SetPopupMenuCanceledFP, "setPopupMenuCanceledFP");
+ LOAD_FP(SetPopupMenuWillBecomeInvisible, SetPopupMenuWillBecomeInvisibleFP, "setPopupMenuWillBecomeInvisibleFP");
+ LOAD_FP(SetPopupMenuWillBecomeVisible, SetPopupMenuWillBecomeVisibleFP, "setPopupMenuWillBecomeVisibleFP");
+
+ LOAD_FP(SetPropertyNameChange, SetPropertyNameChangeFP, "setPropertyNameChangeFP");
+ LOAD_FP(SetPropertyDescriptionChange, SetPropertyDescriptionChangeFP, "setPropertyDescriptionChangeFP");
+ LOAD_FP(SetPropertyStateChange, SetPropertyStateChangeFP, "setPropertyStateChangeFP");
+ LOAD_FP(SetPropertyValueChange, SetPropertyValueChangeFP, "setPropertyValueChangeFP");
+ LOAD_FP(SetPropertySelectionChange, SetPropertySelectionChangeFP, "setPropertySelectionChangeFP");
+ LOAD_FP(SetPropertyTextChange, SetPropertyTextChangeFP, "setPropertyTextChangeFP");
+ LOAD_FP(SetPropertyCaretChange, SetPropertyCaretChangeFP, "setPropertyCaretChangeFP");
+ LOAD_FP(SetPropertyVisibleDataChange, SetPropertyVisibleDataChangeFP, "setPropertyVisibleDataChangeFP");
+ LOAD_FP(SetPropertyChildChange, SetPropertyChildChangeFP, "setPropertyChildChangeFP");
+ LOAD_FP(SetPropertyActiveDescendentChange, SetPropertyActiveDescendentChangeFP, "setPropertyActiveDescendentChangeFP");
+
+ LOAD_FP(SetPropertyTableModelChange, SetPropertyTableModelChangeFP, "setPropertyTableModelChangeFP");
+
+ LOAD_FP(ReleaseJavaObject, ReleaseJavaObjectFP, "releaseJavaObject");
+ LOAD_FP(GetVersionInfo, GetVersionInfoFP, "getVersionInfo");
+
+ LOAD_FP(IsJavaWindow, IsJavaWindowFP, "isJavaWindow");
+ LOAD_FP(IsSameObject, IsSameObjectFP, "isSameObject");
+ LOAD_FP(GetAccessibleContextFromHWND, GetAccessibleContextFromHWNDFP, "getAccessibleContextFromHWND");
+ LOAD_FP(getHWNDFromAccessibleContext, getHWNDFromAccessibleContextFP, "getHWNDFromAccessibleContext");
+
+ LOAD_FP(GetAccessibleContextAt, GetAccessibleContextAtFP, "getAccessibleContextAt");
+ LOAD_FP(GetAccessibleContextWithFocus, GetAccessibleContextWithFocusFP, "getAccessibleContextWithFocus");
+ LOAD_FP(GetAccessibleContextInfo, GetAccessibleContextInfoFP, "getAccessibleContextInfo");
+ LOAD_FP(GetAccessibleChildFromContext, GetAccessibleChildFromContextFP, "getAccessibleChildFromContext");
+ LOAD_FP(GetAccessibleParentFromContext, GetAccessibleParentFromContextFP, "getAccessibleParentFromContext");
+
+ /* begin AccessibleTable */
+ LOAD_FP(getAccessibleTableInfo, getAccessibleTableInfoFP, "getAccessibleTableInfo");
+ LOAD_FP(getAccessibleTableCellInfo, getAccessibleTableCellInfoFP, "getAccessibleTableCellInfo");
+
+ LOAD_FP(getAccessibleTableRowHeader, getAccessibleTableRowHeaderFP, "getAccessibleTableRowHeader");
+ LOAD_FP(getAccessibleTableColumnHeader, getAccessibleTableColumnHeaderFP, "getAccessibleTableColumnHeader");
+
+ LOAD_FP(getAccessibleTableRowDescription, getAccessibleTableRowDescriptionFP, "getAccessibleTableRowDescription");
+ LOAD_FP(getAccessibleTableColumnDescription, getAccessibleTableColumnDescriptionFP, "getAccessibleTableColumnDescription");
+
+ LOAD_FP(getAccessibleTableRowSelectionCount, getAccessibleTableRowSelectionCountFP,
+ "getAccessibleTableRowSelectionCount");
+ LOAD_FP(isAccessibleTableRowSelected, isAccessibleTableRowSelectedFP,
+ "isAccessibleTableRowSelected");
+ LOAD_FP(getAccessibleTableRowSelections, getAccessibleTableRowSelectionsFP,
+ "getAccessibleTableRowSelections");
+
+ LOAD_FP(getAccessibleTableColumnSelectionCount, getAccessibleTableColumnSelectionCountFP,
+ "getAccessibleTableColumnSelectionCount");
+ LOAD_FP(isAccessibleTableColumnSelected, isAccessibleTableColumnSelectedFP,
+ "isAccessibleTableColumnSelected");
+ LOAD_FP(getAccessibleTableColumnSelections, getAccessibleTableColumnSelectionsFP,
+ "getAccessibleTableColumnSelections");
+
+ LOAD_FP(getAccessibleTableRow, getAccessibleTableRowFP,
+ "getAccessibleTableRow");
+ LOAD_FP(getAccessibleTableColumn, getAccessibleTableColumnFP,
+ "getAccessibleTableColumn");
+ LOAD_FP(getAccessibleTableIndex, getAccessibleTableIndexFP,
+ "getAccessibleTableIndex");
+
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ LOAD_FP(getAccessibleRelationSet, getAccessibleRelationSetFP, "getAccessibleRelationSet");
+
+ /* AccessibleHypertext */
+ LOAD_FP(getAccessibleHypertext, getAccessibleHypertextFP, "getAccessibleHypertext");
+ LOAD_FP(activateAccessibleHyperlink, activateAccessibleHyperlinkFP, "activateAccessibleHyperlink");
+ LOAD_FP(getAccessibleHyperlinkCount, getAccessibleHyperlinkCountFP, "getAccessibleHyperlinkCount");
+ LOAD_FP(getAccessibleHypertextExt, getAccessibleHypertextExtFP, "getAccessibleHypertextExt");
+ LOAD_FP(getAccessibleHypertextLinkIndex, getAccessibleHypertextLinkIndexFP, "getAccessibleHypertextLinkIndex");
+ LOAD_FP(getAccessibleHyperlink, getAccessibleHyperlinkFP, "getAccessibleHyperlink");
+
+ /* Accessible KeyBinding, Icon and Action */
+ LOAD_FP(getAccessibleKeyBindings, getAccessibleKeyBindingsFP, "getAccessibleKeyBindings");
+ LOAD_FP(getAccessibleIcons, getAccessibleIconsFP, "getAccessibleIcons");
+ LOAD_FP(getAccessibleActions, getAccessibleActionsFP, "getAccessibleActions");
+ LOAD_FP(doAccessibleActions, doAccessibleActionsFP, "doAccessibleActions");
+
+ /* AccessibleText */
+ LOAD_FP(GetAccessibleTextInfo, GetAccessibleTextInfoFP, "getAccessibleTextInfo");
+ LOAD_FP(GetAccessibleTextItems, GetAccessibleTextItemsFP, "getAccessibleTextItems");
+ LOAD_FP(GetAccessibleTextSelectionInfo, GetAccessibleTextSelectionInfoFP, "getAccessibleTextSelectionInfo");
+ LOAD_FP(GetAccessibleTextAttributes, GetAccessibleTextAttributesFP, "getAccessibleTextAttributes");
+ LOAD_FP(GetAccessibleTextRect, GetAccessibleTextRectFP, "getAccessibleTextRect");
+ LOAD_FP(GetAccessibleTextLineBounds, GetAccessibleTextLineBoundsFP, "getAccessibleTextLineBounds");
+ LOAD_FP(GetAccessibleTextRange, GetAccessibleTextRangeFP, "getAccessibleTextRange");
+
+ LOAD_FP(GetCurrentAccessibleValueFromContext, GetCurrentAccessibleValueFromContextFP, "getCurrentAccessibleValueFromContext");
+ LOAD_FP(GetMaximumAccessibleValueFromContext, GetMaximumAccessibleValueFromContextFP, "getMaximumAccessibleValueFromContext");
+ LOAD_FP(GetMinimumAccessibleValueFromContext, GetMinimumAccessibleValueFromContextFP, "getMinimumAccessibleValueFromContext");
+
+ LOAD_FP(AddAccessibleSelectionFromContext, AddAccessibleSelectionFromContextFP, "addAccessibleSelectionFromContext");
+ LOAD_FP(ClearAccessibleSelectionFromContext, ClearAccessibleSelectionFromContextFP, "clearAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionFromContext, GetAccessibleSelectionFromContextFP, "getAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionCountFromContext, GetAccessibleSelectionCountFromContextFP, "getAccessibleSelectionCountFromContext");
+ LOAD_FP(IsAccessibleChildSelectedFromContext, IsAccessibleChildSelectedFromContextFP, "isAccessibleChildSelectedFromContext");
+ LOAD_FP(RemoveAccessibleSelectionFromContext, RemoveAccessibleSelectionFromContextFP, "removeAccessibleSelectionFromContext");
+ LOAD_FP(SelectAllAccessibleSelectionFromContext, SelectAllAccessibleSelectionFromContextFP, "selectAllAccessibleSelectionFromContext");
+
+ LOAD_FP(setTextContents, setTextContentsFP, "setTextContents");
+ LOAD_FP(getParentWithRole, getParentWithRoleFP, "getParentWithRole");
+ LOAD_FP(getTopLevelObject, getTopLevelObjectFP, "getTopLevelObject");
+ LOAD_FP(getParentWithRoleElseRoot, getParentWithRoleElseRootFP, "getParentWithRoleElseRoot");
+ LOAD_FP(getObjectDepth, getObjectDepthFP, "getObjectDepth");
+ LOAD_FP(getActiveDescendent, getActiveDescendentFP, "getActiveDescendent");
+
+ // additional methods for Teton
+ LOAD_FP(getVirtualAccessibleName, getVirtualAccessibleNameFP, "getVirtualAccessibleName");
+ LOAD_FP(requestFocus, requestFocusFP, "requestFocus");
+ LOAD_FP(selectTextRange, selectTextRangeFP, "selectTextRange");
+ LOAD_FP(getTextAttributesInRange, getTextAttributesInRangeFP, "getTextAttributesInRange");
+ LOAD_FP(getVisibleChildrenCount, getVisibleChildrenCountFP, "getVisibleChildrenCount");
+ LOAD_FP(getVisibleChildren, getVisibleChildrenFP, "getVisibleChildren");
+ LOAD_FP(setCaretPosition, setCaretPositionFP, "setCaretPosition");
+ LOAD_FP(getCaretLocation, getCaretLocationFP, "getCaretLocation");
+
+ LOAD_FP(getEventsWaiting, getEventsWaitingFP, "getEventsWaiting");
+
+ theAccessBridge.Windows_run();
+
+ theAccessBridgeInitializedFlag = TRUE;
+ PrintDebugString("theAccessBridgeInitializedFlag = TRUE");
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+
+ BOOL shutdownAccessBridge() {
+ BOOL result;
+ DWORD error;
+ theAccessBridgeInitializedFlag = FALSE;
+ if (theAccessBridgeInstance != (HANDLE) 0) {
+ result = FreeLibrary(theAccessBridgeInstance);
+ if (result != TRUE) {
+ error = GetLastError();
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetJavaShutdown(fp);
+ }
+ }
+
+ void SetFocusGained(AccessBridge_FocusGainedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusGained(fp);
+ }
+ }
+
+ void SetFocusLost(AccessBridge_FocusLostFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusLost(fp);
+ }
+ }
+
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetCaretUpdate(fp);
+ }
+ }
+
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseClicked(fp);
+ }
+ }
+
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseEntered(fp);
+ }
+ }
+
+ void SetMouseExited(AccessBridge_MouseExitedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseExited(fp);
+ }
+ }
+
+ void SetMousePressed(AccessBridge_MousePressedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMousePressed(fp);
+ }
+ }
+
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseReleased(fp);
+ }
+ }
+
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuCanceled(fp);
+ }
+ }
+
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuDeselected(fp);
+ }
+ }
+
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuSelected(fp);
+ }
+ }
+
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuCanceled(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeInvisible(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeVisible(fp);
+ }
+ }
+
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyNameChange(fp);
+ }
+ }
+
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyDescriptionChange(fp);
+ }
+ }
+
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyStateChange(fp);
+ }
+ }
+
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyValueChange(fp);
+ }
+ }
+
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertySelectionChange(fp);
+ }
+ }
+
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTextChange(fp);
+ }
+ }
+
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyCaretChange(fp);
+ }
+ }
+
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyVisibleDataChange(fp);
+ }
+ }
+
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyChildChange(fp);
+ }
+ }
+
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyActiveDescendentChange(fp);
+ }
+ }
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTableModelChange(fp);
+ }
+ }
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ReleaseJavaObject(vmID, object);
+ }
+ }
+
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetVersionInfo(vmID, info);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ BOOL ret ;
+ ret = theAccessBridge.IsJavaWindow(window);
+ return ret ;
+
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Returns the virtual machine ID and AccessibleContext for a top-level window
+ */
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextFromHWND(target, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the HWND from the AccessibleContext of a top-level window. Returns 0
+ * on error or if the AccessibleContext does not refer to a top-level window.
+ */
+ HWND getHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getHWNDFromAccessibleContext(vmID, accesibleContext);
+ }
+ return (HWND)0;
+ }
+
+ /**
+ * returns whether two objects are the same
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsSameObject(vmID, obj1, obj2);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setTextContents(vmID, accessibleContext, text);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRole(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRoleElseRoot(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTopLevelObject(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getObjectDepth(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getActiveDescendent(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextAt(vmID, acParent, x, y, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextWithFocus(window, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextInfo(vmID, ac, info);
+ }
+ return FALSE;
+ }
+
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleChildFromContext(vmID, ac, index);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleParentFromContext(vmID, ac);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ /* begin AccessibleTable routines */
+
+ /*
+ * get information about an AccessibleTable
+ */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableInfo(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable cell
+ */
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableCellInfo(vmID, accessibleTable, row, column, tableCellInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable row header
+ */
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable column header
+ */
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return a description of an AccessibleTable row header
+ */
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowDescription(vmID, acParent, row);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return a description of an AccessibleTable column header
+ */
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnDescription(vmID, acParent, column);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return the number of rows selected in an AccessibleTable
+ */
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a row is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableRowSelected(vmID, table, row);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of selected rows in an AccessibleTable
+ */
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the number of columns selected in an AccessibleTable
+ */
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a column is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableColumnSelected(vmID, table, column);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of columns selected in an AccessibleTable
+ */
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the row number for a cell at a given index
+ */
+ jint
+ getAccessibleTableRow(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRow(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the column number for a cell at a given index
+ */
+ jint
+ getAccessibleTableColumn(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumn(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the index of a cell at a given row and column
+ */
+ jint
+ getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableIndex(vmID, table, row, column);
+ }
+ return -1;
+ }
+
+ /* end AccessibleTable routines */
+
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextInfo(vmID, at, textInfo, x, y);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextItems(vmID, at, textItems, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextSelectionInfo(vmID, at, textSelection);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextAttributes(vmID, at, index, attributes);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRect(vmID, at, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextLineBounds(vmID, at, index, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRange(vmID, at, start, end, text, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleRelationSet routines
+ */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleRelationSet(vmID, accessibleContext, relationSetInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleHypertext routines
+ */
+
+ // Gets AccessibleHypertext for an AccessibleContext
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertext(vmID, accessibleContext, hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ // Activates an AccessibleHyperlink for an AccessibleContext
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.activateAccessibleHyperlink(vmID, accessibleContext, accessibleHyperlink);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlinkCount(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextExt(vmID,
+ accessibleContext,
+ nStartIndex,
+ hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document;
+ * Maps to AccessibleHypertext.getLinkIndex.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextLinkIndex(vmID,
+ hypertext,
+ nIndex);
+ }
+ return -1;
+ }
+
+ /*
+ * Returns the nth hyperlink in a document.
+ * Maps to AccessibleHypertext.getLink.
+ * Returns -1 on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlink(vmID,
+ hypertext,
+ nIndex,
+ hyperlinkInfo);
+ }
+ return FALSE;
+ }
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleKeyBindings(vmID, accessibleContext, keyBindings);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleIcons(vmID, accessibleContext, icons);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleActions(vmID, accessibleContext, actions);
+ }
+ return FALSE;
+ }
+
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.doAccessibleActions(vmID, accessibleContext, actionsToDo, failure);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetCurrentAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMaximumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMinimumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Accessible Selection routines
+ */
+ void addAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.AddAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void clearAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ClearAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionFromContext(vmID, as, i);
+ }
+ return (JOBJECT64) 0;
+ }
+
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionCountFromContext(vmID, as);
+ }
+ return -1;
+ }
+
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsAccessibleChildSelectedFromContext(vmID, as, i);
+ }
+ return FALSE;
+ }
+
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.RemoveAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SelectAllAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVirtualAccessibleName(vmID, accessibleContext, name, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.requestFocus(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.selectTextRange(vmID, accessibleContext, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTextAttributesInRange(vmID, accessibleContext, startIndex,
+ endIndex, attributes, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildrenCount(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful;
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *visibleChildrenInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildren(vmID, accessibleContext, startIndex,
+ visibleChildrenInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setCaretPosition(vmID, accessibleContext, position);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getCaretLocation(vmID, ac, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting() {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getEventsWaiting();
+ }
+ return FALSE;
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.h b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.h
new file mode 100644
index 00000000..ad007400
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgeCalls.h
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+#include <windows.h>
+#include <jni.h>
+#include "AccessBridgeCallbacks.h"
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define null NULL
+
+ typedef JOBJECT64 AccessibleContext;
+ typedef JOBJECT64 AccessibleText;
+ typedef JOBJECT64 AccessibleValue;
+ typedef JOBJECT64 AccessibleSelection;
+ typedef JOBJECT64 Java_Object;
+ typedef JOBJECT64 PropertyChangeEvent;
+ typedef JOBJECT64 FocusEvent;
+ typedef JOBJECT64 CaretEvent;
+ typedef JOBJECT64 MouseEvent;
+ typedef JOBJECT64 MenuEvent;
+ typedef JOBJECT64 AccessibleTable;
+ typedef JOBJECT64 AccessibleHyperlink;
+ typedef JOBJECT64 AccessibleHypertext;
+
+
+ typedef void (*Windows_runFP) ();
+
+ typedef void (*SetPropertyChangeFP) (AccessBridge_PropertyChangeFP fp);
+
+ typedef void (*SetJavaShutdownFP) (AccessBridge_JavaShutdownFP fp);
+ typedef void (*SetFocusGainedFP) (AccessBridge_FocusGainedFP fp);
+ typedef void (*SetFocusLostFP) (AccessBridge_FocusLostFP fp);
+
+ typedef void (*SetCaretUpdateFP) (AccessBridge_CaretUpdateFP fp);
+
+ typedef void (*SetMouseClickedFP) (AccessBridge_MouseClickedFP fp);
+ typedef void (*SetMouseEnteredFP) (AccessBridge_MouseEnteredFP fp);
+ typedef void (*SetMouseExitedFP) (AccessBridge_MouseExitedFP fp);
+ typedef void (*SetMousePressedFP) (AccessBridge_MousePressedFP fp);
+ typedef void (*SetMouseReleasedFP) (AccessBridge_MouseReleasedFP fp);
+
+ typedef void (*SetMenuCanceledFP) (AccessBridge_MenuCanceledFP fp);
+ typedef void (*SetMenuDeselectedFP) (AccessBridge_MenuDeselectedFP fp);
+ typedef void (*SetMenuSelectedFP) (AccessBridge_MenuSelectedFP fp);
+ typedef void (*SetPopupMenuCanceledFP) (AccessBridge_PopupMenuCanceledFP fp);
+ typedef void (*SetPopupMenuWillBecomeInvisibleFP) (AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ typedef void (*SetPopupMenuWillBecomeVisibleFP) (AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ typedef void (*SetPropertyNameChangeFP) (AccessBridge_PropertyNameChangeFP fp);
+ typedef void (*SetPropertyDescriptionChangeFP) (AccessBridge_PropertyDescriptionChangeFP fp);
+ typedef void (*SetPropertyStateChangeFP) (AccessBridge_PropertyStateChangeFP fp);
+ typedef void (*SetPropertyValueChangeFP) (AccessBridge_PropertyValueChangeFP fp);
+ typedef void (*SetPropertySelectionChangeFP) (AccessBridge_PropertySelectionChangeFP fp);
+ typedef void (*SetPropertyTextChangeFP) (AccessBridge_PropertyTextChangeFP fp);
+ typedef void (*SetPropertyCaretChangeFP) (AccessBridge_PropertyCaretChangeFP fp);
+ typedef void (*SetPropertyVisibleDataChangeFP) (AccessBridge_PropertyVisibleDataChangeFP fp);
+ typedef void (*SetPropertyChildChangeFP) (AccessBridge_PropertyChildChangeFP fp);
+ typedef void (*SetPropertyActiveDescendentChangeFP) (AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ typedef void (*SetPropertyTableModelChangeFP) (AccessBridge_PropertyTableModelChangeFP fp);
+
+ typedef void (*ReleaseJavaObjectFP) (long vmID, Java_Object object);
+
+ typedef BOOL (*GetVersionInfoFP) (long vmID, AccessBridgeVersionInfo *info);
+
+ typedef BOOL (*IsJavaWindowFP) (HWND window);
+ typedef BOOL (*IsSameObjectFP) (long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+ typedef BOOL (*GetAccessibleContextFromHWNDFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef HWND (*getHWNDFromAccessibleContextFP) (long vmID, AccessibleContext ac);
+
+ typedef BOOL (*GetAccessibleContextAtFP) (long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextWithFocusFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextInfoFP) (long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ typedef AccessibleContext (*GetAccessibleChildFromContextFP) (long vmID, AccessibleContext ac, jint i);
+ typedef AccessibleContext (*GetAccessibleParentFromContextFP) (long vmID, AccessibleContext ac);
+
+ /* begin AccessibleTable */
+ typedef BOOL (*getAccessibleTableInfoFP) (long vmID, AccessibleContext ac, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableCellInfoFP) (long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo);
+
+ typedef BOOL (*getAccessibleTableRowHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableColumnHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ typedef AccessibleContext (*getAccessibleTableRowDescriptionFP) (long vmID, AccessibleContext acParent, jint row);
+ typedef AccessibleContext (*getAccessibleTableColumnDescriptionFP) (long vmID, AccessibleContext acParent, jint column);
+
+ typedef jint (*getAccessibleTableRowSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableRowSelectedFP) (long vmID, AccessibleTable table, jint row);
+ typedef BOOL (*getAccessibleTableRowSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableColumnSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableColumnSelectedFP) (long vmID, AccessibleTable table, jint column);
+ typedef BOOL (*getAccessibleTableColumnSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableRowFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableColumnFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableIndexFP) (long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ typedef BOOL (*getAccessibleRelationSetFP) (long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* AccessibleHypertext */
+ typedef BOOL (*getAccessibleHypertextFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef BOOL (*activateAccessibleHyperlinkFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ typedef jint (*getAccessibleHyperlinkCountFP)(const long vmID,
+ const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getAccessibleHypertextExtFP) (const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef jint (*getAccessibleHypertextLinkIndexFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ typedef BOOL (*getAccessibleHyperlinkFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ typedef BOOL (*getAccessibleKeyBindingsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ typedef BOOL (*getAccessibleIconsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ typedef BOOL (*getAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ typedef BOOL (*doAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+ /* AccessibleText */
+
+ typedef BOOL (*GetAccessibleTextInfoFP) (long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ typedef BOOL (*GetAccessibleTextItemsFP) (long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ typedef BOOL (*GetAccessibleTextSelectionInfoFP) (long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ typedef BOOL (*GetAccessibleTextAttributesFP) (long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ typedef BOOL (*GetAccessibleTextRectFP) (long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ typedef BOOL (*GetAccessibleTextLineBoundsFP) (long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ typedef BOOL (*GetAccessibleTextRangeFP) (long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ typedef BOOL (*GetCurrentAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMaximumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMinimumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ typedef void (*AddAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*ClearAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+ typedef JOBJECT64 (*GetAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef int (*GetAccessibleSelectionCountFromContextFP) (long vmID, AccessibleSelection as);
+ typedef BOOL (*IsAccessibleChildSelectedFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*RemoveAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*SelectAllAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+
+ /* Utility methods */
+
+ typedef BOOL (*setTextContentsFP) (const long vmID, const AccessibleContext ac, const wchar_t *text);
+ typedef AccessibleContext (*getParentWithRoleFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getParentWithRoleElseRootFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getTopLevelObjectFP) (const long vmID, const AccessibleContext ac);
+ typedef int (*getObjectDepthFP) (const long vmID, const AccessibleContext ac);
+ typedef AccessibleContext (*getActiveDescendentFP) (const long vmID, const AccessibleContext ac);
+
+
+ typedef BOOL (*getVirtualAccessibleNameFP) (const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ typedef BOOL (*requestFocusFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*selectTextRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex);
+
+ typedef BOOL (*getTextAttributesInRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ typedef int (*getVisibleChildrenCountFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getVisibleChildrenFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *children);
+
+ typedef BOOL (*setCaretPositionFP) (const long vmID, const AccessibleContext accessibleContext, const int position);
+
+ typedef BOOL (*getCaretLocationFP) (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index);
+
+ typedef int (*getEventsWaitingFP) ();
+
+ typedef struct AccessBridgeFPsTag {
+ Windows_runFP Windows_run;
+
+ SetPropertyChangeFP SetPropertyChange;
+
+ SetJavaShutdownFP SetJavaShutdown;
+ SetFocusGainedFP SetFocusGained;
+ SetFocusLostFP SetFocusLost;
+
+ SetCaretUpdateFP SetCaretUpdate;
+
+ SetMouseClickedFP SetMouseClicked;
+ SetMouseEnteredFP SetMouseEntered;
+ SetMouseExitedFP SetMouseExited;
+ SetMousePressedFP SetMousePressed;
+ SetMouseReleasedFP SetMouseReleased;
+
+ SetMenuCanceledFP SetMenuCanceled;
+ SetMenuDeselectedFP SetMenuDeselected;
+ SetMenuSelectedFP SetMenuSelected;
+ SetPopupMenuCanceledFP SetPopupMenuCanceled;
+ SetPopupMenuWillBecomeInvisibleFP SetPopupMenuWillBecomeInvisible;
+ SetPopupMenuWillBecomeVisibleFP SetPopupMenuWillBecomeVisible;
+
+ SetPropertyNameChangeFP SetPropertyNameChange;
+ SetPropertyDescriptionChangeFP SetPropertyDescriptionChange;
+ SetPropertyStateChangeFP SetPropertyStateChange;
+ SetPropertyValueChangeFP SetPropertyValueChange;
+ SetPropertySelectionChangeFP SetPropertySelectionChange;
+ SetPropertyTextChangeFP SetPropertyTextChange;
+ SetPropertyCaretChangeFP SetPropertyCaretChange;
+ SetPropertyVisibleDataChangeFP SetPropertyVisibleDataChange;
+ SetPropertyChildChangeFP SetPropertyChildChange;
+ SetPropertyActiveDescendentChangeFP SetPropertyActiveDescendentChange;
+
+ SetPropertyTableModelChangeFP SetPropertyTableModelChange;
+
+ ReleaseJavaObjectFP ReleaseJavaObject;
+ GetVersionInfoFP GetVersionInfo;
+
+ IsJavaWindowFP IsJavaWindow;
+ IsSameObjectFP IsSameObject;
+ GetAccessibleContextFromHWNDFP GetAccessibleContextFromHWND;
+ getHWNDFromAccessibleContextFP getHWNDFromAccessibleContext;
+
+ GetAccessibleContextAtFP GetAccessibleContextAt;
+ GetAccessibleContextWithFocusFP GetAccessibleContextWithFocus;
+ GetAccessibleContextInfoFP GetAccessibleContextInfo;
+ GetAccessibleChildFromContextFP GetAccessibleChildFromContext;
+ GetAccessibleParentFromContextFP GetAccessibleParentFromContext;
+
+ getAccessibleTableInfoFP getAccessibleTableInfo;
+ getAccessibleTableCellInfoFP getAccessibleTableCellInfo;
+
+ getAccessibleTableRowHeaderFP getAccessibleTableRowHeader;
+ getAccessibleTableColumnHeaderFP getAccessibleTableColumnHeader;
+
+ getAccessibleTableRowDescriptionFP getAccessibleTableRowDescription;
+ getAccessibleTableColumnDescriptionFP getAccessibleTableColumnDescription;
+
+ getAccessibleTableRowSelectionCountFP getAccessibleTableRowSelectionCount;
+ isAccessibleTableRowSelectedFP isAccessibleTableRowSelected;
+ getAccessibleTableRowSelectionsFP getAccessibleTableRowSelections;
+
+ getAccessibleTableColumnSelectionCountFP getAccessibleTableColumnSelectionCount;
+ isAccessibleTableColumnSelectedFP isAccessibleTableColumnSelected;
+ getAccessibleTableColumnSelectionsFP getAccessibleTableColumnSelections;
+
+ getAccessibleTableRowFP getAccessibleTableRow;
+ getAccessibleTableColumnFP getAccessibleTableColumn;
+ getAccessibleTableIndexFP getAccessibleTableIndex;
+
+ getAccessibleRelationSetFP getAccessibleRelationSet;
+
+ getAccessibleHypertextFP getAccessibleHypertext;
+ activateAccessibleHyperlinkFP activateAccessibleHyperlink;
+ getAccessibleHyperlinkCountFP getAccessibleHyperlinkCount;
+ getAccessibleHypertextExtFP getAccessibleHypertextExt;
+ getAccessibleHypertextLinkIndexFP getAccessibleHypertextLinkIndex;
+ getAccessibleHyperlinkFP getAccessibleHyperlink;
+
+ getAccessibleKeyBindingsFP getAccessibleKeyBindings;
+ getAccessibleIconsFP getAccessibleIcons;
+ getAccessibleActionsFP getAccessibleActions;
+ doAccessibleActionsFP doAccessibleActions;
+
+ GetAccessibleTextInfoFP GetAccessibleTextInfo;
+ GetAccessibleTextItemsFP GetAccessibleTextItems;
+ GetAccessibleTextSelectionInfoFP GetAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributesFP GetAccessibleTextAttributes;
+ GetAccessibleTextRectFP GetAccessibleTextRect;
+ GetAccessibleTextLineBoundsFP GetAccessibleTextLineBounds;
+ GetAccessibleTextRangeFP GetAccessibleTextRange;
+
+ GetCurrentAccessibleValueFromContextFP GetCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextFP GetMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextFP GetMinimumAccessibleValueFromContext;
+
+ AddAccessibleSelectionFromContextFP AddAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextFP ClearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextFP GetAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextFP GetAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextFP IsAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextFP RemoveAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextFP SelectAllAccessibleSelectionFromContext;
+
+ setTextContentsFP setTextContents;
+ getParentWithRoleFP getParentWithRole;
+ getTopLevelObjectFP getTopLevelObject;
+ getParentWithRoleElseRootFP getParentWithRoleElseRoot;
+ getObjectDepthFP getObjectDepth;
+ getActiveDescendentFP getActiveDescendent;
+
+ getVirtualAccessibleNameFP getVirtualAccessibleName;
+ requestFocusFP requestFocus;
+ selectTextRangeFP selectTextRange;
+ getTextAttributesInRangeFP getTextAttributesInRange;
+ getVisibleChildrenCountFP getVisibleChildrenCount;
+ getVisibleChildrenFP getVisibleChildren;
+ setCaretPositionFP setCaretPosition;
+ getCaretLocationFP getCaretLocation;
+
+ getEventsWaitingFP getEventsWaiting;
+
+ } AccessBridgeFPs;
+
+
+ /**
+ * Initialize the world
+ */
+ BOOL initializeAccessBridge();
+ BOOL shutdownAccessBridge();
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window);
+
+ // Returns the virtual machine ID and AccessibleContext for a top-level window
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac);
+
+ // Returns the HWND from the AccessibleContext of a top-level window
+ HWND getHWNDFromAccessibleContext(long vmID, AccessibleContext ac);
+
+
+ /**
+ * Event handling routines
+ */
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp);
+ void SetFocusGained(AccessBridge_FocusGainedFP fp);
+ void SetFocusLost(AccessBridge_FocusLostFP fp);
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp);
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp);
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp);
+ void SetMouseExited(AccessBridge_MouseExitedFP fp);
+ void SetMousePressed(AccessBridge_MousePressedFP fp);
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp);
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp);
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp);
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp);
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp);
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp);
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp);
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp);
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp);
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp);
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp);
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp);
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp);
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp);
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp);
+
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object);
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info);
+ HWND GetHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext);
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac);
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index);
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac);
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ /* begin AccessibleTable routines */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable, jint row, jint column,
+ AccessibleTableCellInfo *tableCellInfo);
+
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row);
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column);
+
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row);
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column);
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableRow(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableColumn(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* ----- AccessibleRelationSet routines */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* ----- AccessibleHypertext routines */
+
+ /*
+ * Returns hypertext information associated with a component.
+ */
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Requests that a hyperlink be activated.
+ */
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleHypertext hypertext);
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * Returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document; maps to AccessibleHypertext.getLinkIndex
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ /*
+ * Returns the nth hyperlink in a document
+ * Maps to AccessibleHypertext.getLink.
+ * Returns FALSE on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+ /* Accessible KeyBindings, Icons and Actions */
+
+ /*
+ * Returns a list of key bindings associated with a component.
+ */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ /*
+ * Returns a list of icons associate with a component.
+ */
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ /*
+ * Returns a list of actions that a component can perform.
+ */
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ /*
+ * Request that a list of AccessibleActions be performed by a component.
+ * Returns TRUE if all actions are performed. Returns FALSE
+ * when the first requested action fails in which case "failure"
+ * contains the index of the action that failed.
+ */
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+
+ /* Additional utility methods */
+
+ /*
+ * Returns whether two object references refer to the same object.
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length that can be set is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ /**
+ * Accessible Selection routines
+ */
+ void AddAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void ClearAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as);
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i);
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ /**
+ * Request focus for a component. Returns whether successful.
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful.
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext, const int startIndex,
+ const int endIndex);
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex,
+ VisibleChildrenInfo *visibleChildrenInfo);
+
+ /**
+ * Set the caret to a text position. Returns whether successful.
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position);
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac,
+ AccessibleTextRectInfo *rectInfo, jint index);
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgePackages.h b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgePackages.h
new file mode 100644
index 00000000..478f7c63
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/bridge/AccessBridgePackages.h
@@ -0,0 +1,2215 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * Header file for packages of paramaters passed between Java Accessibility
+ * and native Assistive Technologies
+ */
+
+#ifndef __AccessBridgePackages_H__
+#define __AccessBridgePackages_H__
+
+#include <jni.h>
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef ACCESSBRIDGE_ARCH_LEGACY
+typedef jobject JOBJECT64;
+typedef HWND ABHWND64;
+#define ABHandleToLong
+#define ABLongToHandle
+#else
+typedef jlong JOBJECT64;
+typedef long ABHWND64;
+#define ABHandleToLong HandleToLong
+#define ABLongToHandle LongToHandle
+#endif
+
+#define MAX_BUFFER_SIZE 10240
+#define MAX_STRING_SIZE 1024
+#define SHORT_STRING_SIZE 256
+
+ // object types
+ typedef JOBJECT64 AccessibleContext;
+ typedef JOBJECT64 AccessibleText;
+ typedef JOBJECT64 AccessibleValue;
+ typedef JOBJECT64 AccessibleSelection;
+ typedef JOBJECT64 Java_Object;
+ typedef JOBJECT64 PropertyChangeEvent;
+ typedef JOBJECT64 FocusEvent;
+ typedef JOBJECT64 CaretEvent;
+ typedef JOBJECT64 MouseEvent;
+ typedef JOBJECT64 MenuEvent;
+ typedef JOBJECT64 AccessibleTable;
+ typedef JOBJECT64 AccessibleHyperlink;
+ typedef JOBJECT64 AccessibleHypertext;
+
+ /**
+ ******************************************************
+ * Java event types
+ ******************************************************
+ */
+
+#define cPropertyChangeEvent (jlong) 1 // 1
+#define cFocusGainedEvent (jlong) 2 // 2
+#define cFocusLostEvent (jlong) 4 // 4
+#define cCaretUpdateEvent (jlong) 8 // 8
+#define cMouseClickedEvent (jlong) 16 // 10
+#define cMouseEnteredEvent (jlong) 32 // 20
+#define cMouseExitedEvent (jlong) 64 // 40
+#define cMousePressedEvent (jlong) 128 // 80
+#define cMouseReleasedEvent (jlong) 256 // 100
+#define cMenuCanceledEvent (jlong) 512 // 200
+#define cMenuDeselectedEvent (jlong) 1024 // 400
+#define cMenuSelectedEvent (jlong) 2048 // 800
+#define cPopupMenuCanceledEvent (jlong) 4096 // 1000
+#define cPopupMenuWillBecomeInvisibleEvent (jlong) 8192 // 2000
+#define cPopupMenuWillBecomeVisibleEvent (jlong) 16384 // 4000
+#define cJavaShutdownEvent (jlong) 32768 // 8000
+
+ /**
+ ******************************************************
+ * Accessible Roles
+ * Defines all AccessibleRoles in Local.US
+ ******************************************************
+ */
+
+ /**
+ * Object is used to alert the user about something.
+ */
+#define ACCESSIBLE_ALERT L"alert"
+
+ /**
+ * The header for a column of data.
+ */
+#define ACCESSIBLE_COLUMN_HEADER L"column header"
+
+ /**
+ * Object that can be drawn into and is used to trap
+ * events.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_CANVAS L"canvas"
+
+ /**
+ * A list of choices the user can select from. Also optionally
+ * allows the user to enter a choice of their own.
+ */
+#define ACCESSIBLE_COMBO_BOX L"combo box"
+
+ /**
+ * An iconified internal frame in a DESKTOP_PANE.
+ * see ACCESSIBLE_DESKTOP_PANE
+ * see ACCESSIBLE_INTERNAL_FRAME
+ */
+#define ACCESSIBLE_DESKTOP_ICON L"desktop icon"
+
+ /**
+ * A frame-like object that is clipped by a desktop pane. The
+ * desktop pane, internal frame, and desktop icon objects are
+ * often used to create multiple document interfaces within an
+ * application.
+ * see ACCESSIBLE_DESKTOP_ICON
+ * see ACCESSIBLE_DESKTOP_PANE
+ * see ACCESSIBLE_FRAME
+ */
+#define ACCESSIBLE_INTERNAL_FRAME L"internal frame"
+
+ /**
+ * A pane that supports internal frames and
+ * iconified versions of those internal frames.
+ * see ACCESSIBLE_DESKTOP_ICON
+ * see ACCESSIBLE_INTERNAL_FRAME
+ */
+#define ACCESSIBLE_DESKTOP_PANE L"desktop pane"
+
+ /**
+ * A specialized pane whose primary use is inside a DIALOG
+ * see ACCESSIBLE_DIALOG
+ */
+#define ACCESSIBLE_OPTION_PANE L"option pane"
+
+ /**
+ * A top level window with no title or border.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_DIALOG
+ */
+#define ACCESSIBLE_WINDOW L"window"
+
+ /**
+ * A top level window with a title bar, border, menu bar, etc. It is
+ * often used as the primary window for an application.
+ * see ACCESSIBLE_DIALOG
+ * see ACCESSIBLE_CANVAS
+ * see ACCESSIBLE_WINDOW
+ */
+#define ACCESSIBLE_FRAME L"frame"
+
+ /**
+ * A top level window with title bar and a border. A dialog is similar
+ * to a frame, but it has fewer properties and is often used as a
+ * secondary window for an application.
+ * see ACCESSIBLE_FRAME
+ * see ACCESSIBLE_WINDOW
+ */
+#define ACCESSIBLE_DIALOG L"dialog"
+
+ /**
+ * A specialized dialog that lets the user choose a color.
+ */
+#define ACCESSIBLE_COLOR_CHOOSER L"color chooser"
+
+
+ /**
+ * A pane that allows the user to navigate through
+ * and select the contents of a directory. May be used
+ * by a file chooser.
+ * see ACCESSIBLE_FILE_CHOOSER
+ */
+#define ACCESSIBLE_DIRECTORY_PANE L"directory pane"
+
+ /**
+ * A specialized dialog that displays the files in the directory
+ * and lets the user select a file, browse a different directory,
+ * or specify a filename. May use the directory pane to show the
+ * contents of a directory.
+ * see ACCESSIBLE_DIRECTORY_PANE
+ */
+#define ACCESSIBLE_FILE_CHOOSER L"file chooser"
+
+ /**
+ * An object that fills up space in a user interface. It is often
+ * used in interfaces to tweak the spacing between components,
+ * but serves no other purpose.
+ */
+#define ACCESSIBLE_FILLER L"filler"
+
+ /**
+ * A hypertext anchor
+ */
+#define ACCESSIBLE_HYPERLINK L"hyperlink"
+
+ /**
+ * A small fixed size picture, typically used to decorate components.
+ */
+#define ACCESSIBLE_ICON L"icon"
+
+ /**
+ * An object used to present an icon or short string in an interface.
+ */
+#define ACCESSIBLE_LABEL L"label"
+
+ /**
+ * A specialized pane that has a glass pane and a layered pane as its
+ * children.
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_ROOT_PANE L"root pane"
+
+ /**
+ * A pane that is guaranteed to be painted on top
+ * of all panes beneath it.
+ * see ACCESSIBLE_ROOT_PANE
+ * see ACCESSIBLE_CANVAS
+ */
+#define ACCESSIBLE_GLASS_PANE L"glass pane"
+
+ /**
+ * A specialized pane that allows its children to be drawn in layers,
+ * providing a form of stacking order. This is usually the pane that
+ * holds the menu bar as well as the pane that contains most of the
+ * visual components in a window.
+ * see ACCESSIBLE_GLASS_PANE
+ * see ACCESSIBLE_ROOT_PANE
+ */
+#define ACCESSIBLE_LAYERED_PANE L"layered pane"
+
+ /**
+ * An object that presents a list of objects to the user and allows the
+ * user to select one or more of them. A list is usually contained
+ * within a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ * see ACCESSIBLE_LIST_ITEM
+ */
+#define ACCESSIBLE_LIST L"list"
+
+ /**
+ * An object that presents an element in a list. A list is usually
+ * contained within a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ * see ACCESSIBLE_LIST
+ */
+#define ACCESSIBLE_LIST_ITEM L"list item"
+
+ /**
+ * An object usually drawn at the top of the primary dialog box of
+ * an application that contains a list of menus the user can choose
+ * from. For example, a menu bar might contain menus for "File,"
+ * "Edit," and "Help."
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_POPUP_MENU
+ * see ACCESSIBLE_LAYERED_PANE
+ */
+#define ACCESSIBLE_MENU_BAR L"menu bar"
+
+ /**
+ * A temporary window that is usually used to offer the user a
+ * list of choices, and then hides when the user selects one of
+ * those choices.
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_MENU_ITEM
+ */
+#define ACCESSIBLE_POPUP_MENU L"popup menu"
+
+ /**
+ * An object usually found inside a menu bar that contains a list
+ * of actions the user can choose from. A menu can have any object
+ * as its children, but most often they are menu items, other menus,
+ * or rudimentary objects such as radio buttons, check boxes, or
+ * separators. For example, an application may have an "Edit" menu
+ * that contains menu items for "Cut" and "Paste."
+ * see ACCESSIBLE_MENU_BAR
+ * see ACCESSIBLE_MENU_ITEM
+ * see ACCESSIBLE_SEPARATOR
+ * see ACCESSIBLE_RADIO_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_POPUP_MENU
+ */
+#define ACCESSIBLE_MENU L"menu"
+
+ /**
+ * An object usually contained in a menu that presents an action
+ * the user can choose. For example, the "Cut" menu item in an
+ * "Edit" menu would be an action the user can select to cut the
+ * selected area of text in a document.
+ * see ACCESSIBLE_MENU_BAR
+ * see ACCESSIBLE_SEPARATOR
+ * see ACCESSIBLE_POPUP_MENU
+ */
+#define ACCESSIBLE_MENU_ITEM L"menu item"
+
+ /**
+ * An object usually contained in a menu to provide a visual
+ * and logical separation of the contents in a menu. For example,
+ * the "File" menu of an application might contain menu items for
+ * "Open," "Close," and "Exit," and will place a separator between
+ * "Close" and "Exit" menu items.
+ * see ACCESSIBLE_MENU
+ * see ACCESSIBLE_MENU_ITEM
+ */
+#define ACCESSIBLE_SEPARATOR L"separator"
+
+ /**
+ * An object that presents a series of panels (or page tabs), one at a
+ * time, through some mechanism provided by the object. The most common
+ * mechanism is a list of tabs at the top of the panel. The children of
+ * a page tab list are all page tabs.
+ * see ACCESSIBLE_PAGE_TAB
+ */
+#define ACCESSIBLE_PAGE_TAB_LIST L"page tab list"
+
+ /**
+ * An object that is a child of a page tab list. Its sole child is
+ * the panel that is to be presented to the user when the user
+ * selects the page tab from the list of tabs in the page tab list.
+ * see ACCESSIBLE_PAGE_TAB_LIST
+ */
+#define ACCESSIBLE_PAGE_TAB L"page tab"
+
+ /**
+ * A generic container that is often used to group objects.
+ */
+#define ACCESSIBLE_PANEL L"panel"
+
+ /**
+ * An object used to indicate how much of a task has been completed.
+ */
+#define ACCESSIBLE_PROGRESS_BAR L"progress bar"
+
+ /**
+ * A text object used for passwords, or other places where the
+ * text contents is not shown visibly to the user
+ */
+#define ACCESSIBLE_PASSWORD_TEXT L"password text"
+
+ /**
+ * An object the user can manipulate to tell the application to do
+ * something.
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_PUSH_BUTTON L"push button"
+
+ /**
+ * A specialized push button that can be checked or unchecked, but
+ * does not provide a separate indicator for the current state.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_TOGGLE_BUTTON L"toggle button"
+
+ /**
+ * A choice that can be checked or unchecked and provides a
+ * separate indicator for the current state.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_RADIO_BUTTON
+ */
+#define ACCESSIBLE_CHECK_BOX L"check box"
+
+ /**
+ * A specialized check box that will cause other radio buttons in the
+ * same group to become unchecked when this one is checked.
+ * see ACCESSIBLE_PUSH_BUTTON
+ * see ACCESSIBLE_TOGGLE_BUTTON
+ * see ACCESSIBLE_CHECK_BOX
+ */
+#define ACCESSIBLE_RADIO_BUTTON L"radio button"
+
+ /**
+ * The header for a row of data.
+ */
+#define ACCESSIBLE_ROW_HEADER L"row header"
+
+ /**
+ * An object that allows a user to incrementally view a large amount
+ * of information. Its children can include scroll bars and a viewport.
+ * see ACCESSIBLE_SCROLL_BAR
+ * see ACCESSIBLE_VIEWPORT
+ */
+#define ACCESSIBLE_SCROLL_PANE L"scroll pane"
+
+ /**
+ * An object usually used to allow a user to incrementally view a
+ * large amount of data. Usually used only by a scroll pane.
+ * see ACCESSIBLE_SCROLL_PANE
+ */
+#define ACCESSIBLE_SCROLL_BAR L"scroll bar"
+
+ /**
+ * An object usually used in a scroll pane. It represents the portion
+ * of the entire data that the user can see. As the user manipulates
+ * the scroll bars, the contents of the viewport can change.
+ * see ACCESSIBLE_SCROLL_PANE
+ */
+#define ACCESSIBLE_VIEWPORT L"viewport"
+
+ /**
+ * An object that allows the user to select from a bounded range. For
+ * example, a slider might be used to select a number between 0 and 100.
+ */
+#define ACCESSIBLE_SLIDER L"slider"
+
+ /**
+ * A specialized panel that presents two other panels at the same time.
+ * Between the two panels is a divider the user can manipulate to make
+ * one panel larger and the other panel smaller.
+ */
+#define ACCESSIBLE_SPLIT_PANE L"split pane"
+
+ /**
+ * An object used to present information in terms of rows and columns.
+ * An example might include a spreadsheet application.
+ */
+#define ACCESSIBLE_TABLE L"table"
+
+ /**
+ * An object that presents text to the user. The text is usually
+ * editable by the user as opposed to a label.
+ * see ACCESSIBLE_LABEL
+ */
+#define ACCESSIBLE_TEXT L"text"
+
+ /**
+ * An object used to present hierarchical information to the user.
+ * The individual nodes in the tree can be collapsed and expanded
+ * to provide selective disclosure of the tree's contents.
+ */
+#define ACCESSIBLE_TREE L"tree"
+
+ /**
+ * A bar or palette usually composed of push buttons or toggle buttons.
+ * It is often used to provide the most frequently used functions for an
+ * application.
+ */
+#define ACCESSIBLE_TOOL_BAR L"tool bar"
+
+ /**
+ * An object that provides information about another object. The
+ * accessibleDescription property of the tool tip is often displayed
+ * to the user in a small L"help bubble" when the user causes the
+ * mouse to hover over the object associated with the tool tip.
+ */
+#define ACCESSIBLE_TOOL_TIP L"tool tip"
+
+ /**
+ * An AWT component, but nothing else is known about it.
+ * see ACCESSIBLE_SWING_COMPONENT
+ * see ACCESSIBLE_UNKNOWN
+ */
+#define ACCESSIBLE_AWT_COMPONENT L"awt component"
+
+ /**
+ * A Swing component, but nothing else is known about it.
+ * see ACCESSIBLE_AWT_COMPONENT
+ * see ACCESSIBLE_UNKNOWN
+ */
+#define ACCESSIBLE_SWING_COMPONENT L"swing component"
+
+ /**
+ * The object contains some Accessible information, but its role is
+ * not known.
+ * see ACCESSIBLE_AWT_COMPONENT
+ * see ACCESSIBLE_SWING_COMPONENT
+ */
+#define ACCESSIBLE_UNKNOWN L"unknown"
+
+ /**
+ * A STATUS_BAR is an simple component that can contain
+ * multiple labels of status information to the user.
+ */
+#define ACCESSIBLE_STATUS_BAR L"status bar"
+
+ /**
+ * A DATE_EDITOR is a component that allows users to edit
+ * java.util.Date and java.util.Time objects
+ */
+#define ACCESSIBLE_DATE_EDITOR L"date editor"
+
+ /**
+ * A SPIN_BOX is a simple spinner component and its main use
+ * is for simple numbers.
+ */
+#define ACCESSIBLE_SPIN_BOX L"spin box"
+
+ /**
+ * A FONT_CHOOSER is a component that lets the user pick various
+ * attributes for fonts.
+ */
+#define ACCESSIBLE_FONT_CHOOSER L"font chooser"
+
+ /**
+ * A GROUP_BOX is a simple container that contains a border
+ * around it and contains components inside it.
+ */
+#define ACCESSIBLE_GROUP_BOX L"group box"
+
+ /**
+ * A text header
+ */
+#define ACCESSIBLE_HEADER L"header"
+
+ /**
+ * A text footer
+ */
+#define ACCESSIBLE_FOOTER L"footer"
+
+ /**
+ * A text paragraph
+ */
+#define ACCESSIBLE_PARAGRAPH L"paragraph"
+
+ /**
+ * A ruler is an object used to measure distance
+ */
+#define ACCESSIBLE_RULER L"ruler"
+
+ /**
+ * A role indicating the object acts as a formula for
+ * calculating a value. An example is a formula in
+ * a spreadsheet cell.
+ */
+#define ACCESSIBLE_EDITBAR L"editbar"
+
+ /**
+ * A role indicating the object monitors the progress
+ * of some operation.
+ */
+#define PROGRESS_MONITOR L"progress monitor"
+
+
+ /**
+ ******************************************************
+ * Accessibility event types
+ ******************************************************
+ */
+
+#define cPropertyNameChangeEvent (jlong) 1 // 1
+#define cPropertyDescriptionChangeEvent (jlong) 2 // 2
+#define cPropertyStateChangeEvent (jlong) 4 // 4
+#define cPropertyValueChangeEvent (jlong) 8 // 8
+#define cPropertySelectionChangeEvent (jlong) 16 // 10
+#define cPropertyTextChangeEvent (jlong) 32 // 20
+#define cPropertyCaretChangeEvent (jlong) 64 // 40
+#define cPropertyVisibleDataChangeEvent (jlong) 128 // 80
+#define cPropertyChildChangeEvent (jlong) 256 // 100
+#define cPropertyActiveDescendentChangeEvent (jlong) 512 // 200
+#define cPropertyTableModelChangeEvent (jlong) 1024 // 400
+
+ /**
+ ******************************************************
+ * optional AccessibleContext interfaces
+ *
+ * This version of the bridge reuses the accessibleValue
+ * field in the AccessibleContextInfo struct to represent
+ * additional optional interfaces that are supported by
+ * the Java AccessibleContext. This is backwardly compatable
+ * because the old accessibleValue was set to the BOOL
+ * value TRUE (i.e., 1) if the AccessibleValue interface is
+ * supported.
+ ******************************************************
+ */
+
+#define cAccessibleValueInterface (jlong) 1 // 1 << 1 (TRUE)
+#define cAccessibleActionInterface (jlong) 2 // 1 << 2
+#define cAccessibleComponentInterface (jlong) 4 // 1 << 3
+#define cAccessibleSelectionInterface (jlong) 8 // 1 << 4
+#define cAccessibleTableInterface (jlong) 16 // 1 << 5
+#define cAccessibleTextInterface (jlong) 32 // 1 << 6
+#define cAccessibleHypertextInterface (jlong) 64 // 1 << 7
+
+
+ /**
+ ******************************************************
+ * Accessibility information bundles
+ ******************************************************
+ */
+
+ typedef struct AccessBridgeVersionInfoTag {
+ wchar_t VMversion[SHORT_STRING_SIZE]; // output of "java -version"
+ wchar_t bridgeJavaClassVersion[SHORT_STRING_SIZE]; // version of the AccessBridge.class
+ wchar_t bridgeJavaDLLVersion[SHORT_STRING_SIZE]; // version of JavaAccessBridge.dll
+ wchar_t bridgeWinDLLVersion[SHORT_STRING_SIZE]; // version of WindowsAccessBridge.dll
+ } AccessBridgeVersionInfo;
+
+
+ typedef struct AccessibleContextInfoTag {
+ wchar_t name[MAX_STRING_SIZE]; // the AccessibleName of the object
+ wchar_t description[MAX_STRING_SIZE]; // the AccessibleDescription of the object
+
+ wchar_t role[SHORT_STRING_SIZE]; // localized AccesibleRole string
+ wchar_t role_en_US[SHORT_STRING_SIZE]; // AccesibleRole string in the en_US locale
+ wchar_t states[SHORT_STRING_SIZE]; // localized AccesibleStateSet string (comma separated)
+ wchar_t states_en_US[SHORT_STRING_SIZE]; // AccesibleStateSet string in the en_US locale (comma separated)
+
+ jint indexInParent; // index of object in parent
+ jint childrenCount; // # of children, if any
+
+ jint x; // screen coords in pixels
+ jint y; // "
+ jint width; // pixel width of object
+ jint height; // pixel height of object
+
+ BOOL accessibleComponent; // flags for various additional
+ BOOL accessibleAction; // Java Accessibility interfaces
+ BOOL accessibleSelection; // FALSE if this object doesn't
+ BOOL accessibleText; // implement the additional interface
+ // in question
+
+ // BOOL accessibleValue; // old BOOL indicating whether AccessibleValue is supported
+ BOOL accessibleInterfaces; // new bitfield containing additional interface flags
+
+ } AccessibleContextInfo;
+
+
+
+ // AccessibleText packages
+ typedef struct AccessibleTextInfoTag {
+ jint charCount; // # of characters in this text object
+ jint caretIndex; // index of caret
+ jint indexAtPoint; // index at the passsed in point
+ } AccessibleTextInfo;
+
+ typedef struct AccessibleTextItemsInfoTag {
+ wchar_t letter;
+ wchar_t word[SHORT_STRING_SIZE];
+ wchar_t sentence[MAX_STRING_SIZE];
+ } AccessibleTextItemsInfo;
+
+ typedef struct AccessibleTextSelectionInfoTag {
+ jint selectionStartIndex;
+ jint selectionEndIndex;
+ wchar_t selectedText[MAX_STRING_SIZE];
+ } AccessibleTextSelectionInfo;
+
+ typedef struct AccessibleTextRectInfoTag {
+ jint x; // bounding rect of char at index
+ jint y; // "
+ jint width; // "
+ jint height; // "
+ } AccessibleTextRectInfo;
+
+ // standard attributes for text; note: tabstops are not supported
+ typedef struct AccessibleTextAttributesInfoTag {
+ BOOL bold;
+ BOOL italic;
+ BOOL underline;
+ BOOL strikethrough;
+ BOOL superscript;
+ BOOL subscript;
+
+ wchar_t backgroundColor[SHORT_STRING_SIZE];
+ wchar_t foregroundColor[SHORT_STRING_SIZE];
+ wchar_t fontFamily[SHORT_STRING_SIZE];
+ jint fontSize;
+
+ jint alignment;
+ jint bidiLevel;
+
+ jfloat firstLineIndent;
+ jfloat leftIndent;
+ jfloat rightIndent;
+ jfloat lineSpacing;
+ jfloat spaceAbove;
+ jfloat spaceBelow;
+
+ wchar_t fullAttributesString[MAX_STRING_SIZE];
+ } AccessibleTextAttributesInfo;
+
+ /**
+ ******************************************************
+ * IPC management typedefs
+ ******************************************************
+ */
+
+#define cMemoryMappedNameSize 255
+
+ /**
+ * sent by the WindowsDLL -> the memory-mapped file is setup
+ *
+ */
+ typedef struct MemoryMappedFileCreatedPackageTag {
+// HWND bridgeWindow; // redundant, but easier to get to here...
+ ABHWND64 bridgeWindow; // redundant, but easier to get to here...
+ char filename[cMemoryMappedNameSize];
+ } MemoryMappedFileCreatedPackage;
+
+
+
+
+ /**
+ * sent when a new JavaVM attaches to the Bridge
+ *
+ */
+ typedef struct JavaVMCreatedPackageTag {
+ ABHWND64 bridgeWindow;
+ long vmID;
+ } JavaVMCreatedPackage;
+
+ /**
+ * sent when a JavaVM detatches from the Bridge
+ *
+ */
+ typedef struct JavaVMDestroyedPackageTag {
+ ABHWND64 bridgeWindow;
+ } JavaVMDestroyedPackage;
+
+ /**
+ * sent when a new AT attaches to the Bridge
+ *
+ */
+ typedef struct WindowsATCreatedPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATCreatedPackage;
+
+ /**
+ * sent when an AT detatches from the Bridge
+ *
+ */
+ typedef struct WindowsATDestroyedPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATDestroyedPackage;
+
+
+ /**
+ * sent by JVM Bridges in response to a WindowsATCreate
+ * message; saying "howdy, welcome to the neighborhood"
+ *
+ */
+ typedef struct JavaVMPresentNotificationPackageTag {
+ ABHWND64 bridgeWindow;
+ long vmID;
+ } JavaVMPresentNotificationPackage;
+
+ /**
+ * sent by AT Bridges in response to a JavaVMCreate
+ * message; saying "howdy, welcome to the neighborhood"
+ *
+ */
+ typedef struct WindowsATPresentNotificationPackageTag {
+ ABHWND64 bridgeWindow;
+ } WindowsATPresentNotificationPackage;
+
+
+ /**
+ ******************************************************
+ * Core packages
+ ******************************************************
+ */
+
+ typedef struct ReleaseJavaObjectPackageTag {
+ long vmID;
+ JOBJECT64 object;
+ } ReleaseJavaObjectPackage;
+
+ typedef struct GetAccessBridgeVersionPackageTag {
+ long vmID; // can't get VM info w/out a VM!
+ AccessBridgeVersionInfo rVersionInfo;
+ } GetAccessBridgeVersionPackage;
+
+ typedef struct IsSameObjectPackageTag {
+ long vmID;
+ JOBJECT64 obj1;
+ JOBJECT64 obj2;
+ jboolean rResult;
+ } IsSameObjectPackage;
+
+ /**
+ ******************************************************
+ * Windows packages
+ ******************************************************
+ */
+
+ typedef struct IsJavaWindowPackageTag {
+ jint window;
+ jboolean rResult;
+ } IsJavaWindowPackage;
+
+ typedef struct GetAccessibleContextFromHWNDPackageTag {
+ jint window;
+ long rVMID;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextFromHWNDPackage;
+
+ typedef struct GetHWNDFromAccessibleContextPackageTag {
+ JOBJECT64 accessibleContext;
+ ABHWND64 rHWND;
+ } GetHWNDFromAccessibleContextPackage;
+
+ /**
+******************************************************
+* AccessibleContext packages
+******************************************************
+*/
+
+ typedef struct GetAccessibleContextAtPackageTag {
+ jint x;
+ jint y;
+ long vmID;
+ JOBJECT64 AccessibleContext; // look within this AC
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextAtPackage;
+
+ typedef struct GetAccessibleContextWithFocusPackageTag {
+ long rVMID;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleContextWithFocusPackage;
+
+ typedef struct GetAccessibleContextInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ AccessibleContextInfo rAccessibleContextInfo;
+ } GetAccessibleContextInfoPackage;
+
+ typedef struct GetAccessibleChildFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint childIndex;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleChildFromContextPackage;
+
+ typedef struct GetAccessibleParentFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleParentFromContextPackage;
+
+ /**
+******************************************************
+* AccessibleTable packages
+******************************************************
+*/
+
+#define MAX_TABLE_SELECTIONS 64
+
+ // table information
+ typedef struct AccessibleTableInfoTag {
+ JOBJECT64 caption; // AccesibleContext
+ JOBJECT64 summary; // AccessibleContext
+ jint rowCount;
+ jint columnCount;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 accessibleTable;
+ } AccessibleTableInfo;
+
+ typedef struct GetAccessibleTableInfoPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableInfoPackage;
+
+ // table cell information
+ typedef struct AccessibleTableCellInfoTag {
+ JOBJECT64 accessibleContext;
+ jint index;
+ jint row;
+ jint column;
+ jint rowExtent;
+ jint columnExtent;
+ jboolean isSelected;
+ } AccessibleTableCellInfo;
+
+ typedef struct GetAccessibleTableCellInfoPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jint column;
+ AccessibleTableCellInfo rTableCellInfo;
+ } GetAccessibleTableCellInfoPackage;
+
+ typedef struct GetAccessibleTableRowHeaderPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableRowHeaderPackage;
+
+ typedef struct GetAccessibleTableColumnHeaderPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleTableInfo rTableInfo;
+ } GetAccessibleTableColumnHeaderPackage;
+
+ typedef struct GetAccessibleTableRowDescriptionPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint row;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleTableRowDescriptionPackage;
+
+ typedef struct GetAccessibleTableColumnDescriptionPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint column;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleTableColumnDescriptionPackage;
+
+ typedef struct GetAccessibleTableRowSelectionCountPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint rCount;
+ } GetAccessibleTableRowSelectionCountPackage;
+
+ typedef struct IsAccessibleTableRowSelectedPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jboolean rResult;
+ } IsAccessibleTableRowSelectedPackage;
+
+ typedef struct GetAccessibleTableRowSelectionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint count;
+ jint rSelections[MAX_TABLE_SELECTIONS];
+ } GetAccessibleTableRowSelectionsPackage;
+
+ typedef struct GetAccessibleTableColumnSelectionCountPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint rCount;
+ } GetAccessibleTableColumnSelectionCountPackage;
+
+ typedef struct IsAccessibleTableColumnSelectedPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint column;
+ jboolean rResult;
+ } IsAccessibleTableColumnSelectedPackage;
+
+ typedef struct GetAccessibleTableColumnSelectionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint count;
+ jint rSelections[MAX_TABLE_SELECTIONS];
+ } GetAccessibleTableColumnSelectionsPackage;
+
+
+ typedef struct GetAccessibleTableRowPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint index;
+ jint rRow;
+ } GetAccessibleTableRowPackage;
+
+ typedef struct GetAccessibleTableColumnPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint index;
+ jint rColumn;
+ } GetAccessibleTableColumnPackage;
+
+ typedef struct GetAccessibleTableIndexPackageTag {
+ long vmID;
+ JOBJECT64 accessibleTable;
+ jint row;
+ jint column;
+ jint rIndex;
+ } GetAccessibleTableIndexPackage;
+
+
+ /**
+ ******************************************************
+ * AccessibleRelationSet packages
+ ******************************************************
+ */
+
+#define MAX_RELATION_TARGETS 25
+#define MAX_RELATIONS 5
+
+ typedef struct AccessibleRelationInfoTag {
+ wchar_t key[SHORT_STRING_SIZE];
+ jint targetCount;
+ JOBJECT64 targets[MAX_RELATION_TARGETS]; // AccessibleContexts
+ } AccessibleRelationInfo;
+
+ typedef struct AccessibleRelationSetInfoTag {
+ jint relationCount;
+ AccessibleRelationInfo relations[MAX_RELATIONS];
+ } AccessibleRelationSetInfo;
+
+ typedef struct GetAccessibleRelationSetPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ AccessibleRelationSetInfo rAccessibleRelationSetInfo;
+ } GetAccessibleRelationSetPackage;
+
+ /**
+ ******************************************************
+ * AccessibleHypertext packagess
+ ******************************************************
+ */
+
+#define MAX_HYPERLINKS 64 // maximum number of hyperlinks returned
+
+ // hyperlink information
+ typedef struct AccessibleHyperlinkInfoTag {
+ wchar_t text[SHORT_STRING_SIZE]; // the hyperlink text
+ jint startIndex; //index in the hypertext document where the link begins
+ jint endIndex; //index in the hypertext document where the link ends
+ JOBJECT64 accessibleHyperlink; // AccessibleHyperlink object
+ } AccessibleHyperlinkInfo;
+
+ // hypertext information
+ typedef struct AccessibleHypertextInfoTag {
+ jint linkCount; // number of hyperlinks
+ AccessibleHyperlinkInfo links[MAX_HYPERLINKS]; // the hyperlinks
+ JOBJECT64 accessibleHypertext; // AccessibleHypertext object
+ } AccessibleHypertextInfo;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ typedef struct GetAccessibleHypertextPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext with hypertext
+ AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext
+ } GetAccessibleHypertextPackage;
+
+ // struct for sending an message to activate a hyperlink
+ typedef struct ActivateAccessibleHyperlinkPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext containing the link
+ JOBJECT64 accessibleHyperlink; // the link to activate
+ BOOL rResult; // hyperlink activation return value
+ } ActivateAccessibleHyperlinkPackage;
+
+ // struct for sending a message to get the number of hyperlinks in a component
+ typedef struct GetAccessibleHyperlinkCountPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext containing AccessibleHypertext
+ jint rLinkCount; // link count return value
+ } GetAccessibleHyperlinkCountPackage;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ // starting at a specified index in the document
+ typedef struct GetAccessibleHypertextExtPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext with hypertext
+ jint startIndex; // start index in document
+ AccessibleHypertextInfo rAccessibleHypertextInfo; // returned hypertext
+ BOOL rSuccess; // whether call succeeded
+ } GetAccessibleHypertextExtPackage;
+
+ // struct for sending a message to get the nth hyperlink in a document;
+ // maps to AccessibleHypertext.getLink
+ typedef struct GetAccessibleHyperlinkPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 hypertext; // AccessibleHypertext
+ jint linkIndex; // hyperlink index
+ AccessibleHyperlinkInfo rAccessibleHyperlinkInfo; // returned hyperlink
+ } GetAccessibleHyperlinkPackage;
+
+ // struct for sending a message to get the index into an array
+ // of hyperlinks that is associated with a character index in a
+ // document; maps to AccessibleHypertext.getLinkIndex
+ typedef struct GetAccessibleHypertextLinkIndexPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 hypertext; // AccessibleHypertext
+ jint charIndex; // character index in document
+ jint rLinkIndex; // returned hyperlink index
+ } GetAccessibleHypertextLinkIndexPackage;
+
+ /**
+ ******************************************************
+ * Accessible Key Bindings packages
+ ******************************************************
+ */
+
+#define MAX_KEY_BINDINGS 10
+
+ // keyboard character modifiers
+#define ACCESSIBLE_SHIFT_KEYSTROKE 1
+#define ACCESSIBLE_CONTROL_KEYSTROKE 2
+#define ACCESSIBLE_META_KEYSTROKE 4
+#define ACCESSIBLE_ALT_KEYSTROKE 8
+#define ACCESSIBLE_ALT_GRAPH_KEYSTROKE 16
+#define ACCESSIBLE_BUTTON1_KEYSTROKE 32
+#define ACCESSIBLE_BUTTON2_KEYSTROKE 64
+#define ACCESSIBLE_BUTTON3_KEYSTROKE 128
+#define ACCESSIBLE_FKEY_KEYSTROKE 256 // F key pressed, character contains 1-24
+#define ACCESSIBLE_CONTROLCODE_KEYSTROKE 512 // Control code key pressed, character contains control code.
+
+// The supported control code keys are:
+#define ACCESSIBLE_VK_BACK_SPACE 8
+#define ACCESSIBLE_VK_DELETE 127
+#define ACCESSIBLE_VK_DOWN 40
+#define ACCESSIBLE_VK_END 35
+#define ACCESSIBLE_VK_HOME 36
+#define ACCESSIBLE_VK_INSERT 155
+#define ACCESSIBLE_VK_KP_DOWN 225
+#define ACCESSIBLE_VK_KP_LEFT 226
+#define ACCESSIBLE_VK_KP_RIGHT 227
+#define ACCESSIBLE_VK_KP_UP 224
+#define ACCESSIBLE_VK_LEFT 37
+#define ACCESSIBLE_VK_PAGE_DOWN 34
+#define ACCESSIBLE_VK_PAGE_UP 33
+#define ACCESSIBLE_VK_RIGHT 39
+#define ACCESSIBLE_VK_UP 38
+
+ // a key binding associates with a component
+ typedef struct AccessibleKeyBindingInfoTag {
+ jchar character; // the key character
+ jint modifiers; // the key modifiers
+ } AccessibleKeyBindingInfo;
+
+ // all of the key bindings associated with a component
+ typedef struct AccessibleKeyBindingsTag {
+ int keyBindingsCount; // number of key bindings
+ AccessibleKeyBindingInfo keyBindingInfo[MAX_KEY_BINDINGS];
+ } AccessibleKeyBindings;
+
+ // struct to get the key bindings associated with a component
+ typedef struct GetAccessibleKeyBindingsPackageTag {
+ long vmID; // the virtual machine id
+ JOBJECT64 accessibleContext; // the component
+ AccessibleKeyBindings rAccessibleKeyBindings; // the key bindings
+ } GetAccessibleKeyBindingsPackage;
+
+ /**
+******************************************************
+* AccessibleIcon packages
+******************************************************
+*/
+#define MAX_ICON_INFO 8
+
+ // an icon assocated with a component
+ typedef struct AccessibleIconInfoTag {
+ wchar_t description[SHORT_STRING_SIZE]; // icon description
+ jint height; // icon height
+ jint width; // icon width
+ } AccessibleIconInfo;
+
+ // all of the icons associated with a component
+ typedef struct AccessibleIconsTag {
+ jint iconsCount; // number of icons
+ AccessibleIconInfo iconInfo[MAX_ICON_INFO]; // the icons
+ } AccessibleIcons;
+
+ // struct to get the icons associated with a component
+ typedef struct GetAccessibleIconsPackageTag {
+ long vmID; // the virtual machine id
+ JOBJECT64 accessibleContext; // the component
+ AccessibleIcons rAccessibleIcons; // the icons
+ } GetAccessibleIconsPackage;
+
+
+ /**
+******************************************************
+* AccessibleAction packages
+******************************************************
+*/
+#define MAX_ACTION_INFO 256
+#define MAX_ACTIONS_TO_DO 32
+
+ // an action assocated with a component
+ typedef struct AccessibleActionInfoTag {
+ wchar_t name[SHORT_STRING_SIZE]; // action name
+ } AccessibleActionInfo;
+
+ // all of the actions associated with a component
+ typedef struct AccessibleActionsTag {
+ jint actionsCount; // number of actions
+ AccessibleActionInfo actionInfo[MAX_ACTION_INFO]; // the action information
+ } AccessibleActions;
+
+ // struct for requesting the actions associated with a component
+ typedef struct GetAccessibleActionsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext; // the component
+ AccessibleActions rAccessibleActions; // the actions
+ } GetAccessibleActionsPackage;
+
+ // list of AccessibleActions to do
+ typedef struct AccessibleActionsToDoTag {
+ jint actionsCount; // number of actions to do
+ AccessibleActionInfo actions[MAX_ACTIONS_TO_DO];// the accessible actions to do
+ } AccessibleActionsToDo;
+
+ // struct for sending an message to do one or more actions
+ typedef struct DoAccessibleActionsPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // component to do the action
+ AccessibleActionsToDo actionsToDo; // the accessible actions to do
+ BOOL rResult; // action return value
+ jint failure; // index of action that failed if rResult is FALSE
+ } DoAccessibleActionsPackage;
+
+ /**
+******************************************************
+* AccessibleText packages
+******************************************************
+*/
+
+ typedef struct GetAccessibleTextInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint x;
+ jint y;
+ AccessibleTextInfo rTextInfo;
+ } GetAccessibleTextInfoPackage;
+
+ typedef struct GetAccessibleTextItemsPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextItemsInfo rTextItemsInfo;
+ } GetAccessibleTextItemsPackage;
+
+ typedef struct GetAccessibleTextSelectionInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ AccessibleTextSelectionInfo rTextSelectionItemsInfo;
+ } GetAccessibleTextSelectionInfoPackage;
+
+ typedef struct GetAccessibleTextAttributeInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextAttributesInfo rAttributeInfo;
+ } GetAccessibleTextAttributeInfoPackage;
+
+ typedef struct GetAccessibleTextRectInfoPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextRectInfo rTextRectInfo;
+ } GetAccessibleTextRectInfoPackage;
+
+ typedef struct GetCaretLocationPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ AccessibleTextRectInfo rTextRectInfo;
+ } GetCaretLocationPackage;
+
+ typedef struct GetAccessibleTextLineBoundsPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ jint rLineStart;
+ jint rLineEnd;
+ } GetAccessibleTextLineBoundsPackage;
+
+ typedef struct GetAccessibleTextRangePackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint start;
+ jint end;
+ wchar_t rText[MAX_BUFFER_SIZE];
+ } GetAccessibleTextRangePackage;
+
+ /**
+******************************************************
+*
+* Utility method packages
+******************************************************
+*/
+
+ typedef struct SetTextContentsPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext; // the text field
+ wchar_t text[MAX_STRING_SIZE]; // the text
+ BOOL rResult;
+ } SetTextContentsPackage;
+
+ typedef struct GetParentWithRolePackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above
+ JOBJECT64 rAccessibleContext;
+ } GetParentWithRolePackage;
+
+ typedef struct GetTopLevelObjectPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetTopLevelObjectPackage;
+
+ typedef struct GetParentWithRoleElseRootPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ wchar_t role[SHORT_STRING_SIZE]; // one of Accessible Roles above
+ JOBJECT64 rAccessibleContext;
+ } GetParentWithRoleElseRootPackage;
+
+ typedef struct GetObjectDepthPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ jint rResult;
+ } GetObjectDepthPackage;
+
+ typedef struct GetActiveDescendentPackageTag {
+ long vmID;
+ JOBJECT64 accessibleContext;
+ JOBJECT64 rAccessibleContext;
+ } GetActiveDescendentPackage;
+
+ /**
+******************************************************
+* AccessibleValue packages
+******************************************************
+*/
+
+ typedef struct GetCurrentAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetCurrentAccessibleValueFromContextPackage;
+
+ typedef struct GetMaximumAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetMaximumAccessibleValueFromContextPackage;
+
+ typedef struct GetMinimumAccessibleValueFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ wchar_t rValue[SHORT_STRING_SIZE];
+ } GetMinimumAccessibleValueFromContextPackage;
+
+
+ /**
+******************************************************
+* AccessibleSelection packages
+******************************************************
+*/
+
+ typedef struct AddAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ } AddAccessibleSelectionFromContextPackage;
+
+ typedef struct ClearAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ } ClearAccessibleSelectionFromContextPackage;
+
+ typedef struct GetAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ JOBJECT64 rAccessibleContext;
+ } GetAccessibleSelectionFromContextPackage;
+
+ typedef struct GetAccessibleSelectionCountFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint rCount;
+ } GetAccessibleSelectionCountFromContextPackage;
+
+ typedef struct IsAccessibleChildSelectedFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ jboolean rResult;
+ } IsAccessibleChildSelectedFromContextPackage;
+
+ typedef struct RemoveAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ jint index;
+ } RemoveAccessibleSelectionFromContextPackage;
+
+ typedef struct SelectAllAccessibleSelectionFromContextPackageTag {
+ long vmID;
+ JOBJECT64 AccessibleContext;
+ } SelectAllAccessibleSelectionFromContextPackage;
+
+
+ /**
+******************************************************
+* Java Event Notification Registration packages
+******************************************************
+*/
+
+ typedef struct AddJavaEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } AddJavaEventNotificationPackage;
+
+ typedef struct RemoveJavaEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } RemoveJavaEventNotificationPackage;
+
+
+ /**
+******************************************************
+* Accessibility Event Notification Registration packages
+******************************************************
+*/
+
+ typedef struct AddAccessibilityEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } AddAccessibilityEventNotificationPackage;
+
+ typedef struct RemoveAccessibilityEventNotificationPackageTag {
+ jlong type;
+ //HWND DLLwindow;
+ ABHWND64 DLLwindow;
+ } RemoveAccessibilityEventNotificationPackage;
+
+
+ /**
+******************************************************
+* Accessibility Property Change Event packages
+******************************************************
+*/
+
+ typedef struct PropertyCaretChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ jint oldPosition;
+ jint newPosition;
+ } PropertyCaretChangePackage;
+
+ typedef struct PropertyDescriptionChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldDescription[SHORT_STRING_SIZE];
+ wchar_t newDescription[SHORT_STRING_SIZE];
+ } PropertyDescriptionChangePackage;
+
+ typedef struct PropertyNameChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldName[SHORT_STRING_SIZE];
+ wchar_t newName[SHORT_STRING_SIZE];
+ } PropertyNameChangePackage;
+
+ typedef struct PropertySelectionChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertySelectionChangePackage;
+
+ typedef struct PropertyStateChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldState[SHORT_STRING_SIZE];
+ wchar_t newState[SHORT_STRING_SIZE];
+ } PropertyStateChangePackage;
+
+ typedef struct PropertyTextChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertyTextChangePackage;
+
+ typedef struct PropertyValueChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldValue[SHORT_STRING_SIZE];
+ wchar_t newValue[SHORT_STRING_SIZE];
+ } PropertyValueChangePackage;
+
+ typedef struct PropertyVisibleDataChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PropertyVisibleDataChangePackage;
+
+ typedef struct PropertyChildChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ JOBJECT64 oldChildAccessibleContext;
+ JOBJECT64 newChildAccessibleContext;
+ } PropertyChildChangePackage;
+
+ typedef struct PropertyActiveDescendentChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ JOBJECT64 oldActiveDescendentAccessibleContext;
+ JOBJECT64 newActiveDescendentAccessibleContext;
+ } PropertyActiveDescendentChangePackage;
+
+
+ // String format for newValue is:
+ // "type" one of "INSERT", "UPDATE" or "DELETE"
+ // "firstRow"
+ // "lastRow"
+ // "firstColumn"
+ // "lastColumn"
+ //
+ // oldValue is currently unused
+ //
+ typedef struct PropertyTableModelChangePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ wchar_t oldValue[SHORT_STRING_SIZE];
+ wchar_t newValue[SHORT_STRING_SIZE];
+ } PropertyTableModelChangePackage;
+
+
+ /**
+******************************************************
+* Property Change Event packages
+******************************************************
+*/
+
+ /*
+ typedef struct PropertyChangePackageTag {
+ long vmID;
+ jobject Event;
+ jobject AccessibleContextSource;
+ char propertyName[SHORT_STRING_SIZE];
+ char oldValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getOldValue().toString()
+ char newValue[SHORT_STRING_SIZE]; // PropertyChangeEvent().getNewValue().toString()
+ } PropertyChangePackage;
+ */
+
+ /*
+ * Java shutdown event package
+ */
+ typedef struct JavaShutdownPackageTag {
+ long vmID;
+ } JavaShutdownPackage;
+
+
+ /**
+******************************************************
+* Focus Event packages
+******************************************************
+*/
+
+ typedef struct FocusGainedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } FocusGainedPackage;
+
+ typedef struct FocusLostPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } FocusLostPackage;
+
+
+ /**
+******************************************************
+* Caret Event packages
+******************************************************
+*/
+
+ typedef struct CaretUpdatePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } CaretUpdatePackage;
+
+
+ /**
+******************************************************
+* Mouse Event packages
+******************************************************
+*/
+
+ typedef struct MouseClickedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseClickedPackage;
+
+ typedef struct MouseEnteredPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseEnteredPackage;
+
+ typedef struct MouseExitedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseExitedPackage;
+
+ typedef struct MousePressedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MousePressedPackage;
+
+ typedef struct MouseReleasedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MouseReleasedPackage;
+
+
+ /**
+******************************************************
+* Menu/PopupMenu Event packages
+******************************************************
+*/
+
+ typedef struct MenuCanceledPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuCanceledPackage;
+
+ typedef struct MenuDeselectedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuDeselectedPackage;
+
+ typedef struct MenuSelectedPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } MenuSelectedPackage;
+
+
+ typedef struct PopupMenuCanceledPackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuCanceledPackage;
+
+ typedef struct PopupMenuWillBecomeInvisiblePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuWillBecomeInvisiblePackage;
+
+ typedef struct PopupMenuWillBecomeVisiblePackageTag {
+ long vmID;
+ JOBJECT64 Event;
+ JOBJECT64 AccessibleContextSource;
+ } PopupMenuWillBecomeVisiblePackage;
+
+ /**
+******************************************************
+* Additional methods for Teton
+******************************************************
+*/
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ typedef struct GetVirtualAccessibleNamePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ wchar_t rName[MAX_STRING_SIZE];
+ int len;
+ } GetVirtualAccessibleNamePackage;
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ typedef struct RequestFocusPackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ } RequestFocusPackage;
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ typedef struct SelectTextRangePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint startIndex;
+ jint endIndex;
+ } SelectTextRangePackage;
+
+ /**
+ * Gets the number of contiguous characters with the same attributes.
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ typedef struct GetTextAttributesInRangePackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint startIndex; // start index (inclusive)
+ jint endIndex; // end index (inclusive)
+ AccessibleTextAttributesInfo attributes; // character attributes to match
+ short rLength; // number of contiguous characters with matching attributes
+ } GetTextAttributesInRangePackage;
+
+#define MAX_VISIBLE_CHILDREN 256
+
+ // visible children information
+ typedef struct VisibleChildenInfoTag {
+ int returnedChildrenCount; // number of children returned
+ AccessibleContext children[MAX_VISIBLE_CHILDREN]; // the visible children
+ } VisibleChildrenInfo;
+
+ // struct for sending a message to get the number of visible children
+ typedef struct GetVisibleChildrenCountPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext of parent component
+ jint rChildrenCount; // visible children count return value
+ } GetVisibleChildrenCountPackage;
+
+ // struct for sending a message to get the hypertext for an AccessibleContext
+ // starting at a specified index in the document
+ typedef struct GetVisibleChildrenPackageTag {
+ long vmID; // the virtual machine ID
+ JOBJECT64 accessibleContext; // AccessibleContext of parent component
+ jint startIndex; // start index for retrieving children
+ VisibleChildrenInfo rVisibleChildrenInfo; // returned info
+ BOOL rSuccess; // whether call succeeded
+ } GetVisibleChildrenPackage;
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ typedef struct SetCaretPositionPackageTag {
+ long vmID;
+ AccessibleContext accessibleContext;
+ jint position;
+ } SetCaretPositionPackage;
+
+
+ /**
+ ******************************************************
+ * Wrapping up all of the packages
+ ******************************************************
+ */
+
+ /**
+ * What is the type of this package
+ */
+ typedef enum PackageType {
+
+ cMemoryMappedFileCreatedPackage = 0x11000,
+
+ // many of these will go away...
+ cJavaVMCreatedPackage = 0x10000,
+ cJavaVMDestroyedPackage,
+ cWindowsATCreatedPackage,
+ cWindowsATDestroyedPackage,
+ cJavaVMPresentNotificationPackage,
+ cWindowsATPresentNotificationPackage,
+
+ cReleaseJavaObjectPackage = 1,
+ cGetAccessBridgeVersionPackage = 2,
+
+ cGetAccessibleContextFromHWNDPackage = 0x10,
+ cIsJavaWindowPackage,
+ cGetHWNDFromAccessibleContextPackage,
+
+ cGetAccessibleContextAtPackage = 0x100,
+ cGetAccessibleContextWithFocusPackage,
+ cGetAccessibleContextInfoPackage,
+ cGetAccessibleChildFromContextPackage,
+ cGetAccessibleParentFromContextPackage,
+ cIsSameObjectPackage,
+
+ cGetAccessibleTextInfoPackage = 0x200,
+ cGetAccessibleTextItemsPackage,
+ cGetAccessibleTextSelectionInfoPackage,
+ cGetAccessibleTextAttributeInfoPackage,
+ cGetAccessibleTextRectInfoPackage,
+ cGetAccessibleTextLineBoundsPackage,
+ cGetAccessibleTextRangePackage,
+
+ cGetCurrentAccessibleValueFromContextPackage = 0x300,
+ cGetMaximumAccessibleValueFromContextPackage,
+ cGetMinimumAccessibleValueFromContextPackage,
+
+ cAddAccessibleSelectionFromContextPackage = 0x400,
+ cClearAccessibleSelectionFromContextPackage,
+ cGetAccessibleSelectionFromContextPackage,
+ cGetAccessibleSelectionCountFromContextPackage,
+ cIsAccessibleChildSelectedFromContextPackage,
+ cRemoveAccessibleSelectionFromContextPackage,
+ cSelectAllAccessibleSelectionFromContextPackage,
+
+ cAddJavaEventNotificationPackage = 0x900,
+ cRemoveJavaEventNotificationPackage,
+ cAddAccessibilityEventNotificationPackage,
+ cRemoveAccessibilityEventNotificationPackage,
+
+ cPropertyChangePackage = 0x1000,
+
+ cJavaShutdownPackage = 0x1010,
+ cFocusGainedPackage,
+ cFocusLostPackage,
+
+ cCaretUpdatePackage = 0x1020,
+
+ cMouseClickedPackage = 0x1030,
+ cMouseEnteredPackage,
+ cMouseExitedPackage,
+ cMousePressedPackage,
+ cMouseReleasedPackage,
+
+ cMenuCanceledPackage = 0x1040,
+ cMenuDeselectedPackage,
+ cMenuSelectedPackage,
+ cPopupMenuCanceledPackage,
+ cPopupMenuWillBecomeInvisiblePackage,
+ cPopupMenuWillBecomeVisiblePackage,
+
+ cPropertyCaretChangePackage = 0x1100,
+ cPropertyDescriptionChangePackage,
+ cPropertyNameChangePackage,
+ cPropertySelectionChangePackage,
+ cPropertyStateChangePackage,
+ cPropertyTextChangePackage,
+ cPropertyValueChangePackage,
+ cPropertyVisibleDataChangePackage,
+ cPropertyChildChangePackage,
+ cPropertyActiveDescendentChangePackage,
+
+
+ // AccessibleTable
+ cGetAccessibleTableInfoPackage = 0x1200,
+ cGetAccessibleTableCellInfoPackage,
+
+ cGetAccessibleTableRowHeaderPackage,
+ cGetAccessibleTableColumnHeaderPackage,
+
+ cGetAccessibleTableRowDescriptionPackage,
+ cGetAccessibleTableColumnDescriptionPackage,
+
+ cGetAccessibleTableRowSelectionCountPackage,
+ cIsAccessibleTableRowSelectedPackage,
+ cGetAccessibleTableRowSelectionsPackage,
+
+ cGetAccessibleTableColumnSelectionCountPackage,
+ cIsAccessibleTableColumnSelectedPackage,
+ cGetAccessibleTableColumnSelectionsPackage,
+
+ cGetAccessibleTableRowPackage,
+ cGetAccessibleTableColumnPackage,
+ cGetAccessibleTableIndexPackage,
+
+ cPropertyTableModelChangePackage,
+
+
+ // AccessibleRelationSet
+ cGetAccessibleRelationSetPackage = 0x1300,
+
+ // AccessibleHypertext
+ cGetAccessibleHypertextPackage = 0x1400,
+ cActivateAccessibleHyperlinkPackage,
+ cGetAccessibleHyperlinkCountPackage,
+ cGetAccessibleHypertextExtPackage,
+ cGetAccessibleHypertextLinkIndexPackage,
+ cGetAccessibleHyperlinkPackage,
+
+ // Accessible KeyBinding, Icon and Action
+ cGetAccessibleKeyBindingsPackage = 0x1500,
+ cGetAccessibleIconsPackage,
+ cGetAccessibleActionsPackage,
+ cDoAccessibleActionsPackage,
+
+ // Utility methods
+ cSetTextContentsPackage = 0x1600,
+ cGetParentWithRolePackage,
+ cGetTopLevelObjectPackage,
+ cGetParentWithRoleElseRootPackage,
+ cGetObjectDepthPackage,
+ cGetActiveDescendentPackage,
+
+ // Additional methods for Teton
+ cGetVirtualAccessibleNamePackage = 0x1700,
+ cRequestFocusPackage,
+ cSelectTextRangePackage,
+ cGetTextAttributesInRangePackage,
+ cGetSameTextAttributesInRangePackage,
+ cGetVisibleChildrenCountPackage,
+ cGetVisibleChildrenPackage,
+ cSetCaretPositionPackage,
+ cGetCaretLocationPackage
+
+
+ } PackageType;
+
+
+ /**
+ * Union of all package contents
+ */
+ typedef union AllPackagesTag {
+
+ // Initial Rendezvous packages
+ MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage;
+
+ JavaVMCreatedPackage javaVMCreatedPackage;
+ JavaVMDestroyedPackage javaVMDestroyedPackage;
+ WindowsATCreatedPackage windowsATCreatedPackage;
+ WindowsATDestroyedPackage windowsATDestroyedPackage;
+ JavaVMPresentNotificationPackage javaVMPresentNotificationPackage;
+ WindowsATPresentNotificationPackage windowsATPresentNotificationPackage;
+
+ // Core packages
+ ReleaseJavaObjectPackage releaseJavaObject;
+ GetAccessBridgeVersionPackage getAccessBridgeVersion;
+
+ // Window packages
+ GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND;
+ GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext;
+
+ // AccessibleContext packages
+ GetAccessibleContextAtPackage getAccessibleContextAt;
+ GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus;
+ GetAccessibleContextInfoPackage getAccessibleContextInfo;
+ GetAccessibleChildFromContextPackage getAccessibleChildFromContext;
+ GetAccessibleParentFromContextPackage getAccessibleParentFromContext;
+
+ // AccessibleText packages
+ GetAccessibleTextInfoPackage getAccessibleTextInfo;
+ GetAccessibleTextItemsPackage getAccessibleTextItems;
+ GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo;
+ GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo;
+ GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds;
+ GetAccessibleTextRangePackage getAccessibleTextRange;
+
+ // AccessibleValue packages
+ GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext;
+
+ // AccessibleSelection packages
+ AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext;
+
+ // Event Notification Registration packages
+ AddJavaEventNotificationPackage addJavaEventNotification;
+ RemoveJavaEventNotificationPackage removeJavaEventNotification;
+ AddAccessibilityEventNotificationPackage addAccessibilityEventNotification;
+ RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification;
+
+ // Event contents packages
+ // PropertyChangePackage propertyChange;
+ PropertyCaretChangePackage propertyCaretChangePackage;
+ PropertyDescriptionChangePackage propertyDescriptionChangePackage;
+ PropertyNameChangePackage propertyNameChangePackage;
+ PropertySelectionChangePackage propertySelectionChangePackage;
+ PropertyStateChangePackage propertyStateChangePackage;
+ PropertyTextChangePackage propertyTextChangePackage;
+ PropertyValueChangePackage propertyValueChangePackage;
+ PropertyVisibleDataChangePackage propertyVisibleDataChangePackage;
+ PropertyChildChangePackage propertyChildChangePackage;
+ PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage;
+
+ PropertyTableModelChangePackage propertyTableModelChangePackage;
+
+ JavaShutdownPackage JavaShutdown;
+ FocusGainedPackage focusGained;
+ FocusLostPackage focusLost;
+
+ CaretUpdatePackage caretUpdate;
+
+ MouseClickedPackage mouseClicked;
+ MouseEnteredPackage mouseEntered;
+ MouseExitedPackage mouseExited;
+ MousePressedPackage mousePressed;
+ MouseReleasedPackage mouseReleased;
+
+ MenuCanceledPackage menuCanceled;
+ MenuDeselectedPackage menuDeselected;
+ MenuSelectedPackage menuSelected;
+ PopupMenuCanceledPackage popupMenuCanceled;
+ PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible;
+ PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible;
+
+ // AccessibleRelationSet
+ GetAccessibleRelationSetPackage getAccessibleRelationSet;
+
+ // AccessibleHypertext
+ GetAccessibleHypertextPackage _getAccessibleHypertext;
+ ActivateAccessibleHyperlinkPackage _activateAccessibleHyperlink;
+ GetAccessibleHyperlinkCountPackage _getAccessibleHyperlinkCount;
+ GetAccessibleHypertextExtPackage _getAccessibleHypertextExt;
+ GetAccessibleHypertextLinkIndexPackage _getAccessibleHypertextLinkIndex;
+ GetAccessibleHyperlinkPackage _getAccessibleHyperlink;
+
+ // Accessible KeyBinding, Icon and Action
+ GetAccessibleKeyBindingsPackage getAccessibleKeyBindings;
+ GetAccessibleIconsPackage getAccessibleIcons;
+ GetAccessibleActionsPackage getAccessibleActions;
+ DoAccessibleActionsPackage doAccessibleActions;
+
+ // utility methods
+ SetTextContentsPackage _setTextContents;
+ GetParentWithRolePackage _getParentWithRole;
+ GetTopLevelObjectPackage _getTopLevelObject;
+ GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot;
+ GetObjectDepthPackage _getObjectDepth;
+ GetActiveDescendentPackage _getActiveDescendent;
+
+ // Additional methods for Teton
+ GetVirtualAccessibleNamePackage _getVirtualAccessibleName;
+ RequestFocusPackage _requestFocus;
+ SelectTextRangePackage _selectTextRange;
+ GetTextAttributesInRangePackage _getTextAttributesInRange;
+ GetVisibleChildrenCountPackage _getVisibleChildrenCount;
+ GetVisibleChildrenPackage _getVisibleChildren;
+ SetCaretPositionPackage _setCaretPosition;
+
+ } AllPackages;
+
+
+ /**
+ * Union of all Java-initiated package contents
+ */
+ typedef union JavaInitiatedPackagesTag {
+
+ // Initial Rendezvous packages
+ JavaVMCreatedPackage javaVMCreatedPackage;
+ JavaVMDestroyedPackage javaVMDestroyedPackage;
+ JavaVMPresentNotificationPackage javaVMPresentNotificationPackage;
+
+ // Event contents packages
+ PropertyCaretChangePackage propertyCaretChangePackage;
+ PropertyDescriptionChangePackage propertyDescriptionChangePackage;
+ PropertyNameChangePackage propertyNameChangePackage;
+ PropertySelectionChangePackage propertySelectionChangePackage;
+ PropertyStateChangePackage propertyStateChangePackage;
+ PropertyTextChangePackage propertyTextChangePackage;
+ PropertyValueChangePackage propertyValueChangePackage;
+ PropertyVisibleDataChangePackage propertyVisibleDataChangePackage;
+ PropertyChildChangePackage propertyChildChangePackage;
+ PropertyActiveDescendentChangePackage propertyActiveDescendentChangePackage;
+
+ PropertyTableModelChangePackage propertyTableModelChangePackage;
+
+ JavaShutdownPackage JavaShutdown;
+ FocusGainedPackage focusGained;
+ FocusLostPackage focusLost;
+
+ CaretUpdatePackage caretUpdate;
+
+ MouseClickedPackage mouseClicked;
+ MouseEnteredPackage mouseEntered;
+ MouseExitedPackage mouseExited;
+ MousePressedPackage mousePressed;
+ MouseReleasedPackage mouseReleased;
+
+ MenuCanceledPackage menuCanceled;
+ MenuDeselectedPackage menuDeselected;
+ MenuSelectedPackage menuSelected;
+ PopupMenuCanceledPackage popupMenuCanceled;
+ PopupMenuWillBecomeInvisiblePackage popupMenuWillBecomeInvisible;
+ PopupMenuWillBecomeVisiblePackage popupMenuWillBecomeVisible;
+
+ } JavaInitiatedPackages;
+
+
+ /**
+ * Union of all Windows-initiated package contents
+ */
+ typedef union WindowsInitiatedPackagesTag {
+
+ // Initial Rendezvous packages
+ MemoryMappedFileCreatedPackage memoryMappedFileCreatedPackage;
+
+ WindowsATCreatedPackage windowsATCreatedPackage;
+ WindowsATDestroyedPackage windowsATDestroyedPackage;
+ WindowsATPresentNotificationPackage windowsATPresentNotificationPackage;
+
+ // Core packages
+ ReleaseJavaObjectPackage releaseJavaObject;
+ GetAccessBridgeVersionPackage getAccessBridgeVersion;
+
+ // Window packages
+ GetAccessibleContextFromHWNDPackage getAccessibleContextFromHWND;
+ GetHWNDFromAccessibleContextPackage getHWNDFromAccessibleContext;
+
+ // AccessibleContext packages
+ GetAccessibleContextAtPackage getAccessibleContextAt;
+ GetAccessibleContextWithFocusPackage getAccessibleContextWithFocus;
+ GetAccessibleContextInfoPackage getAccessibleContextInfo;
+ GetAccessibleChildFromContextPackage getAccessibleChildFromContext;
+ GetAccessibleParentFromContextPackage getAccessibleParentFromContext;
+
+ // AccessibleText packages
+ GetAccessibleTextInfoPackage getAccessibleTextInfo;
+ GetAccessibleTextItemsPackage getAccessibleTextItems;
+ GetAccessibleTextSelectionInfoPackage getAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributeInfoPackage getAccessibleTextAttributeInfo;
+ GetAccessibleTextRectInfoPackage getAccessibleTextRectInfo;
+ GetAccessibleTextLineBoundsPackage getAccessibleTextLineBounds;
+ GetAccessibleTextRangePackage getAccessibleTextRange;
+
+ // AccessibleValue packages
+ GetCurrentAccessibleValueFromContextPackage getCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextPackage getMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextPackage getMinimumAccessibleValueFromContext;
+
+ // AccessibleSelection packages
+ AddAccessibleSelectionFromContextPackage addAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextPackage clearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextPackage getAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextPackage getAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextPackage isAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextPackage removeAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextPackage selectAllAccessibleSelectionFromContext;
+
+ // Event Notification Registration packages
+ AddJavaEventNotificationPackage addJavaEventNotification;
+ RemoveJavaEventNotificationPackage removeJavaEventNotification;
+ AddAccessibilityEventNotificationPackage addAccessibilityEventNotification;
+ RemoveAccessibilityEventNotificationPackage removeAccessibilityEventNotification;
+
+ // AccessibleTable
+ GetAccessibleTableInfoPackage _getAccessibleTableInfo;
+ GetAccessibleTableCellInfoPackage _getAccessibleTableCellInfo;
+
+ GetAccessibleTableRowHeaderPackage _getAccessibleTableRowHeader;
+ GetAccessibleTableColumnHeaderPackage _getAccessibleTableColumnHeader;
+
+ GetAccessibleTableRowDescriptionPackage _getAccessibleTableRowDescription;
+ GetAccessibleTableColumnDescriptionPackage _getAccessibleTableColumnDescription;
+
+ GetAccessibleTableRowSelectionCountPackage _getAccessibleTableRowSelectionCount;
+ IsAccessibleTableRowSelectedPackage _isAccessibleTableRowSelected;
+ GetAccessibleTableRowSelectionsPackage _getAccessibleTableRowSelections;
+
+ GetAccessibleTableColumnSelectionCountPackage _getAccessibleTableColumnSelectionCount;
+ IsAccessibleTableColumnSelectedPackage _isAccessibleTableColumnSelected;
+ GetAccessibleTableColumnSelectionsPackage _getAccessibleTableColumnSelections;
+
+ GetAccessibleTableRowPackage _getAccessibleTableRow;
+ GetAccessibleTableColumnPackage _getAccessibleTableColumn;
+ GetAccessibleTableIndexPackage _getAccessibleTableIndex;
+
+ // AccessibleRelationSet
+ GetAccessibleRelationSetPackage _getAccessibleRelationSet;
+
+ // Accessible KeyBindings, Icons and Actions
+ GetAccessibleKeyBindingsPackage _getAccessibleKeyBindings;
+ GetAccessibleIconsPackage _getAccessibleIcons;
+ GetAccessibleActionsPackage _getAccessibleActions;
+ DoAccessibleActionsPackage _doAccessibleActions;
+
+
+ IsSameObjectPackage _isSameObject;
+
+ // utility methods
+ SetTextContentsPackage _setTextContents;
+ GetParentWithRolePackage _getParentWithRole;
+ GetTopLevelObjectPackage _getTopLevelObject;
+ GetParentWithRoleElseRootPackage _getParentWithRoleElseRoot;
+ GetObjectDepthPackage _getObjectDepth;
+ GetActiveDescendentPackage _getActiveDescendent;
+
+ // Additional methods for Teton
+ GetVirtualAccessibleNamePackage _getVirtualAccessibleName;
+ RequestFocusPackage _requestFocus;
+ SelectTextRangePackage _selectTextRange;
+ GetTextAttributesInRangePackage _getTextAttributesInRange;
+ GetVisibleChildrenCountPackage _getVisibleChildrenCount;
+ GetVisibleChildrenPackage _getVisibleChildren;
+ SetCaretPositionPackage _setCaretPosition;
+
+
+ } WindowsInitiatedPackages;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/demos/java/jni/gs_jni/include/win32/jawt_md.h b/demos/java/jni/gs_jni/include/win32/jawt_md.h
new file mode 100644
index 00000000..66e7256a
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/jawt_md.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JAWT_MD_H_
+#define _JAVASOFT_JAWT_MD_H_
+
+#include <windows.h>
+#include "jawt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Win32-specific declarations for AWT native interface.
+ * See notes in jawt.h for an example of use.
+ */
+typedef struct jawt_Win32DrawingSurfaceInfo {
+ /* Native window, DDB, or DIB handle */
+ union {
+ HWND hwnd;
+ HBITMAP hbitmap;
+ void* pbits;
+ };
+ /*
+ * This HDC should always be used instead of the HDC returned from
+ * BeginPaint() or any calls to GetDC().
+ */
+ HDC hdc;
+ HPALETTE hpalette;
+} JAWT_Win32DrawingSurfaceInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_JAVASOFT_JAWT_MD_H_ */
diff --git a/demos/java/jni/gs_jni/include/win32/jni_md.h b/demos/java/jni/gs_jni/include/win32/jni_md.h
new file mode 100644
index 00000000..38080013
--- /dev/null
+++ b/demos/java/jni/gs_jni/include/win32/jni_md.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT __declspec(dllexport)
+#define JNIIMPORT __declspec(dllimport)
+#define JNICALL __stdcall
+
+typedef long jint;
+typedef __int64 jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/demos/java/jni/gs_jni/jni_util.cpp b/demos/java/jni/gs_jni/jni_util.cpp
new file mode 100644
index 00000000..0a99f8bc
--- /dev/null
+++ b/demos/java/jni/gs_jni/jni_util.cpp
@@ -0,0 +1,593 @@
+#include "jni_util.h"
+
+#include <exception>
+#include <string.h>
+#include <varargs.h>
+#include <string>
+
+using namespace util;
+
+jfieldID util::getFieldID(JNIEnv *env, jobject object, const char *field, const char *sig)
+{
+ if (env == NULL || object == NULL || field == NULL || sig == NULL)
+ return NULL;
+
+ jclass clazz = env->GetObjectClass(object);
+ jfieldID fieldID = env->GetFieldID(clazz, field, sig);
+ if (fieldID == NULL)
+ {
+ const char *className = getClassName(env, clazz);
+
+ const std::string full = std::string(className) + "." + field;
+ throwNoSuchFieldError(env, full.c_str());
+
+ freeClassName(className);
+
+ return NULL;
+ }
+
+ return fieldID;
+}
+
+jmethodID util::getMethodID(JNIEnv *env, jobject object, const char *method, const char *sig)
+{
+ if (env == NULL || object == NULL || method == NULL || sig == NULL)
+ return NULL;
+
+ jclass clazz = env->GetObjectClass(object);
+
+ jmethodID methodID = env->GetMethodID(clazz, method, sig);
+ if (methodID == NULL)
+ {
+ const char *className = getClassName(env, clazz);
+
+ const std::string full = std::string(className) + "." + method + sig;
+ throwNoSuchMethodError(env, full.c_str());
+
+ freeClassName(className);
+
+ env->DeleteLocalRef(clazz);
+ return NULL;
+ }
+
+ env->DeleteLocalRef(clazz);
+ return methodID;
+}
+
+
+void util::setByteArrayField(JNIEnv *env, jobject object, const char *field, jbyteArray value)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "[B");
+ if (fieldID == NULL)
+ return;
+
+ env->SetObjectField(object, fieldID, value);
+}
+
+void util::setByteArrayField(JNIEnv *env, jobject object, const char *field, const char *string)
+{
+ jsize len = (jsize)strlen(string);
+ jbyteArray byteArray = env->NewByteArray(len);
+ env->SetByteArrayRegion(byteArray, 0, len, (const signed char *)string);
+ setByteArrayField(env, object, field, byteArray);
+}
+
+jbyteArray util::getByteArrayField(JNIEnv *env, jobject object, const char *field)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "[B");
+ if (fieldID == NULL)
+ return NULL;
+
+ return (jbyteArray)env->GetObjectField(object, fieldID);
+}
+
+char **util::jbyteArray2DToCharArray(JNIEnv *env, jobjectArray array)
+{
+ jboolean copy = false;
+ jsize len = env->GetArrayLength(array);
+ char **result = new char*[len];
+ for (jsize i = 0; i < len; i++)
+ {
+ jbyteArray byteArrayObject = (jbyteArray)env->GetObjectArrayElement(array, i);
+ char *elem = (char *)env->GetByteArrayElements(byteArrayObject, &copy);
+ jsize slen = strlen(elem);
+ char *nstring = new char[slen + 1LL];
+ nstring[slen] = 0;
+ memcpy(nstring, elem, slen);
+ result[i] = nstring;
+ }
+ return result;
+}
+
+void util::delete2DByteArray(int count, char **array)
+{
+ for (int i = 0; i < count; i++)
+ {
+ delete[] array[i];
+ array[i] = NULL;
+ }
+ delete[] array;
+}
+
+void util::setLongField(JNIEnv *env, jobject object, const char *field, jlong value)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "J");
+ if (fieldID == NULL)
+ return;
+
+ env->SetLongField(object, fieldID, value);
+}
+
+jlong util::getLongField(JNIEnv *env, jobject object, const char *field)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "J");
+ if (fieldID == NULL)
+ return 0LL;
+
+ return env->GetLongField(object, fieldID);
+}
+
+void util::setIntField(JNIEnv *env, jobject object, const char *field, jint value)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "I");
+ if (fieldID == NULL)
+ return;
+
+ env->SetIntField(object, fieldID, value);
+}
+
+jint util::getIntField(JNIEnv *env, jobject object, const char *field)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "I");
+ if (fieldID == NULL)
+ return 0;
+
+ return env->GetIntField(object, fieldID);
+}
+
+int util::callIntMethod(JNIEnv *env, jobject object, const char *method, const char *sig, ...)
+{
+ jmethodID methodID = getMethodID(env, object, method, sig);
+ if (methodID == NULL)
+ return 0;
+
+ va_list args;
+ int result;
+ va_start(args, sig);
+ result = env->CallIntMethodV(object, methodID, args);
+ va_end(args);
+
+ return result;
+}
+
+void util::setObjectField(JNIEnv *env, jobject object, const char *field, jobject value)
+{
+ jfieldID fieldID = getFieldID(env, object, field, "Ljava/lang/Object;");
+ if (fieldID == NULL)
+ return;
+
+ env->SetObjectField(object, fieldID, value);
+}
+
+jobject util::getObjectField(JNIEnv *env, jobject object, const char *field)
+{
+
+ jfieldID fieldID = getFieldID(env, object, field, "Ljava/lang/Object;");
+ if (fieldID == NULL)
+ return 0;
+
+ return env->GetObjectField(object, fieldID);
+}
+
+jobject util::toWrapperType(JNIEnv *env, jboolean value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Boolean";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(Z)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jbyte value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Byte";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(Z)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jchar value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Character";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(C)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jshort value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Short";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(S)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jint value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Integer";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(I)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jlong value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Long";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(J)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jfloat value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Float";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(F)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jobject util::toWrapperType(JNIEnv *env, jdouble value)
+{
+ jclass clazz;
+ static const char *const className = "java/lang/Double";
+ clazz = env->FindClass(className);
+ if (!clazz)
+ {
+ throwNoClassDefError(env, className);
+ return NULL;
+ }
+ jmethodID methodID = env->GetMethodID(clazz, "<init>", "(D)V");
+ jobject result = env->NewObject(clazz, methodID, value);
+ return result;
+}
+
+jboolean util::toBoolean(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jboolean on NULL jobject");
+ return JNI_FALSE;
+ }
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "Z");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetBooleanField(wrapped, fieldID);
+}
+
+jbyte util::toByte(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jbyte on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "B");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetByteField(wrapped, fieldID);
+}
+
+jchar util::toChar(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jchar on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "C");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetCharField(wrapped, fieldID);
+}
+
+jshort util::toShort(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jshort on NULL jobject");
+ return 0;
+ }
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "S");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetShortField(wrapped, fieldID);
+}
+
+jint util::toInt(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jint on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "I");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetIntField(wrapped, fieldID);
+}
+
+jlong util::toLong(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jlong on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "J");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetLongField(wrapped, fieldID);
+}
+
+jfloat util::toFloat(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jfloat on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "F");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetFloatField(wrapped, fieldID);
+}
+
+jdouble util::toDouble(JNIEnv *env, jobject wrapped)
+{
+ if (!wrapped)
+ {
+ throwNullPointerException(env, "attempting to get wrapped jdouble on NULL jobject");
+ return 0;
+ }
+
+ jclass clazz = env->GetObjectClass(wrapped);
+ jfieldID fieldID = env->GetFieldID(clazz, "value", "D");
+ if (fieldID == NULL)
+ {
+ throwNoSuchFieldError(env, "value");
+ return 0;
+ }
+ return env->GetDoubleField(wrapped, fieldID);
+}
+
+jint util::throwNoClassDefError(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "java/lang/NoClassDefFoundError";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ throw std::exception("Failed to find java.lang.NoClassDefFoundError");
+
+ return env->ThrowNew(exClass, message);
+}
+
+jint util::throwNullPointerException(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "java/lang/NullPointerException";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ return throwNoClassDefError(env, className);
+
+ return env->ThrowNew(exClass, message);
+}
+
+jint util::throwNoSuchMethodError(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "java/lang/NoSuchMethodError";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ return throwNoClassDefError(env, className);
+
+ return env->ThrowNew(exClass, message);
+}
+
+jint util::throwNoSuchFieldError(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "java/lang/NoSuchFieldError";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ return throwNoClassDefError(env, className);
+
+ return env->ThrowNew(exClass, message);
+}
+
+jint util::throwAllocationError(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "com/artifex/gsjava/util/AllocationError";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ return throwNoClassDefError(env, className);
+
+ return env->ThrowNew(exClass, message);
+}
+
+jint util::throwIllegalArgumentException(JNIEnv *env, const char *message)
+{
+ if (env == NULL)
+ return -1;
+
+ jclass exClass;
+ static const char *const className = "java/lang/IllegalArgumentException";
+
+ exClass = env->FindClass(className);
+ if (exClass == NULL)
+ return throwNoClassDefError(env, className);
+
+ return env->ThrowNew(exClass, message);
+}
+
+const char *util::getClassName(JNIEnv *env, jclass clazz)
+{
+ jclass clsClazz = env->GetObjectClass(clazz);
+
+ jmethodID methodId = env->GetMethodID(clsClazz, "getName", "()Ljava/lang/String;");
+ jstring className = (jstring)env->CallObjectMethod(clazz, methodId);
+ const char *chars = env->GetStringUTFChars(className, NULL);
+ jsize len = env->GetStringLength(className);
+ char *cstr = new char[len + 1LL];
+ if (cstr == NULL)
+ {
+ env->ReleaseStringUTFChars(className, chars);
+ env->DeleteLocalRef(className);
+ return NULL;
+ }
+ cstr[len] = 0;
+ memcpy(cstr, chars, len);
+ env->ReleaseStringUTFChars(className, chars);
+ env->DeleteLocalRef(className);
+ return cstr;
+}
+
+void util::freeClassName(const char *className)
+{
+ delete[] className;
+}
+
+util::Reference::Reference(JNIEnv *env) : Reference(m_env, NULL)
+{
+}
+
+util::Reference::Reference(JNIEnv *env, jobject object) : m_env(env), m_object(NULL)
+{
+ if (!object)
+ {
+ static const char *const CLASS_NAME = "com/artifex/gsjava/util/Reference";
+ jclass refClass = env->FindClass(CLASS_NAME);
+ if (refClass == NULL)
+ {
+ throwNoClassDefError(env, CLASS_NAME);
+ return;
+ }
+ jmethodID constructor = env->GetMethodID(refClass, "<init>", "()V");
+ if (constructor == NULL)
+ {
+ throwNoSuchMethodError(env, "com/artifex/gsjava/util/Reference.<init>()V");
+ return;
+ }
+ object = m_env->NewObject(refClass, constructor);
+ if (object == NULL)
+ return;
+ }
+ m_object = m_env->NewGlobalRef(object);
+}
+
+util::Reference::~Reference()
+{
+ if (m_object)
+ m_env->DeleteGlobalRef(m_object);
+}
diff --git a/demos/java/jni/gs_jni/jni_util.h b/demos/java/jni/gs_jni/jni_util.h
new file mode 100644
index 00000000..6439712e
--- /dev/null
+++ b/demos/java/jni/gs_jni/jni_util.h
@@ -0,0 +1,377 @@
+#pragma once
+
+#include <jni.h>
+
+#define REFERENCE_VALUE_FILED_NAME "value"
+
+namespace util
+{
+
+ typedef class Reference Reference;
+ typedef class LongReference LongReference;
+ typedef class IntReference IntReference;
+ typedef class ByteArrayReference ByteArrayReference;
+
+ /*!
+ Returns the field ID of a field inside an object, checking if it exists and ensuring
+ all arguments are non-null. If the field is not found, the Java exception NoSuchFieldError
+ will be thrown and NULL will be returned.
+
+ @param env A JNIEnv.
+ @param object The object to find the field in.
+ @param field The name of the field.
+ @param sig The field's signature.
+
+ @return The field ID, or NULL if the field is not found, or any argument is NULL.
+ */
+ jfieldID getFieldID(JNIEnv *env, jobject object, const char *field, const char *sig);
+
+ /*!
+ Returns the method ID of a method inside an object, checking if it exists and ensuring
+ all arguments are non-null. If the method is not found, the Java exception NoSuchMethodError
+ will be thrown and NULL will be returned.
+
+ @param env A JNIEnv.
+ @param object The object to find the method in.
+ @param method The name of the method.
+ @param sig The method's signature.
+
+ @return The method ID, or NULL if the method is not found, or any argument is NULL.
+ */
+ jmethodID getMethodID(JNIEnv *env, jobject object, const char *method, const char *sig);
+
+ /*!
+ Sets a byte array field of an object.
+
+ @param env A JNIEnv.
+ @param object The object containing a byte array field.
+ @param field The name of the field to set.
+ @param value The value to set the field to.
+ */
+ void setByteArrayField(JNIEnv *env, jobject object, const char *field, jbyteArray value);
+
+ /*!
+ Sets a byte array field of an object.
+
+ @param env A JNIEnv.
+ @param object The object containing a byte array field.
+ @param field The name of the field to set.
+ @param string The value to set the field to.
+ */
+ void setByteArrayField(JNIEnv *env, jobject object, const char *field, const char *string);
+
+ /*!
+ Returns the value of a byte array field in an object.
+
+ @param env A JNIEnv.
+ @param object The object to get the byte array field from.
+ @param field The name of the field.
+
+ @return The value of the field.
+ */
+ jbyteArray getByteArrayField(JNIEnv *env, jobject object, const char *field);
+
+ /*!
+ Converts a 2D Java byte array to a 2D C++ char array. The returned
+ value should be used in delete2DByteArray() when finished.
+
+ @param env A JNIEnv.
+ @param array The array to convert.
+
+ @return The 2D C++ char array.
+ */
+ char **jbyteArray2DToCharArray(JNIEnv *env, jobjectArray array);
+
+ /*!
+ Deletes a 2D C++ char array allocated from jbyteArray2DToCharArray().
+
+ @param count The size of the array.
+ @param array The array to delete.
+ */
+ void delete2DByteArray(int count, char **array);
+
+ /*!
+ Sets a long field of an object.
+
+ @param env A JNIEnv.
+ @param object The object containing a long field.
+ @param field The name of the field to set.
+ @param value The value to set the field to.
+ */
+ void setLongField(JNIEnv *env, jobject object, const char *field, jlong value);
+
+ /*!
+ Returns the value of a long field in an object.
+
+ @param env A JNIEnv.
+ @param object The object to get the long field from.
+ @param field The name of the long field.
+
+ @return The value of the long field.
+ */
+ jlong getLongField(JNIEnv *env, jobject object, const char *field);
+
+ /*!
+ Sets a int field of an object.
+
+ @param env A JNIEnv.
+ @param object The object containing a int field.
+ @param field The name of the field to set.
+ @param value The value to set the field to.
+ */
+ void setIntField(JNIEnv *env, jobject object, const char *field, jint value);
+
+ /*!
+ Returns the value of a int field in an object.
+
+ @param env A JNIEnv.
+ @param object The object to get the int field from.
+ @param field The name of the int field.
+
+ @return The value of the int field.
+ */
+ jint getIntField(JNIEnv *env, jobject object, const char *field);
+
+ /*!
+ Calls a Java method returning an int.
+
+ @param env A JNIEnv.
+ @param object The object containing the int method.
+ @param name The name of the method.
+ @param sig The method's signature.
+ @param ... The varargs representing the object's arguments in their respective order.
+ */
+ int callIntMethod(JNIEnv *env, jobject object, const char *name, const char *sig, ...);
+
+ void setObjectField(JNIEnv *env, jobject object, const char *field, jobject value);
+
+ jobject getObjectField(JNIEnv *env, jobject object, const char *field);
+
+ jobject toWrapperType(JNIEnv *env, jboolean value);
+ jobject toWrapperType(JNIEnv *env, jbyte value);
+ jobject toWrapperType(JNIEnv *env, jchar value);
+ jobject toWrapperType(JNIEnv *env, jshort value);
+ jobject toWrapperType(JNIEnv *env, jint value);
+ jobject toWrapperType(JNIEnv *env, jlong value);
+ jobject toWrapperType(JNIEnv *env, jfloat value);
+ jobject toWrapperType(JNIEnv *env, jdouble value);
+
+ jboolean toBoolean(JNIEnv *env, jobject wrapped);
+ jbyte toByte(JNIEnv *env, jobject wrapped);
+ jchar toChar(JNIEnv *env, jobject wrapped);
+ jshort toShort(JNIEnv *env, jobject wrapped);
+ jint toInt(JNIEnv *env, jobject wrapped);
+ jlong toLong(JNIEnv *env, jobject wrapped);
+ jfloat toFloat(JNIEnv *env, jobject wrapped);
+ jdouble toDouble(JNIEnv *env, jobject wrapped);
+
+ /*!
+ Throws the Java exception java.lang.NoClassDefFoundError with a message. The function
+ calling this function should immediately return after calling this function.
+
+ @param env A JNIEnv.
+ @param message The message of the error.
+
+ @return The result of throwing the error.
+ */
+ jint throwNoClassDefError(JNIEnv *env, const char *message);
+
+ /*!
+ Throws the Java exception java.lang.NullPointerException with a message. The function
+ calling this function should immediately return after calling this function.
+
+ @param env A JNIEnv.
+ @param message The message of the exception.
+
+ @return The result of throwing the exception.
+ */
+ jint throwNullPointerException(JNIEnv *env, const char *message);
+
+ /*!
+ Throws the Java exception java.lang.NoSuchMethodError with a message. The function
+ calling this function should immediately return after calling this function.
+
+ @param env A JNIEnv.
+ @param message The message of the exception.
+
+ @return The result of throwing the exception.
+ */
+ jint throwNoSuchMethodError(JNIEnv *env, const char *message);
+
+ /*!
+ Throws the Java exception java.lang.NoSuchFieldError with a message. The function
+ calling this function should immediately return after calling this function.
+
+ @param env A JNIEnv.
+ @param message The message of the exception.
+
+ @return The result of throwing the exception.
+ */
+ jint throwNoSuchFieldError(JNIEnv *env, const char *message);
+
+ /*!
+ Throws the Java exception com.artifex.gsjava.util.AllocationError with a message.
+ The function calling this function should immediately return after calling this function.
+
+ @param env A JNIEnv.
+ @param message The message of the exception.
+
+ @return The result of throwing the exception.
+ */
+ jint throwAllocationError(JNIEnv *env, const char *message);
+
+ jint throwIllegalArgumentException(JNIEnv *env, const char *message);
+
+ /*!
+ Returns the name of a jclass. The name is dynamically allocated and after usage,
+ freeClassName() should be called.
+
+ @param env A JNIEnv.
+ @param clazz A jclass.
+
+ @return The name of the class, or NULL if env or clazz are NULL.
+ */
+ const char *getClassName(JNIEnv *env, jclass clazz);
+
+ /*!
+ Frees a class name generated from getClassName().
+
+ @param className The className generated from getClassName().
+ */
+ void freeClassName(const char *className);
+
+ class Reference
+ {
+ public:
+
+ static inline void setValueField(JNIEnv *env, jobject object, jobject value)
+ {
+ setObjectField(env, object, "value", value);
+ }
+
+ static inline jobject getValueField(JNIEnv *env, jobject object)
+ {
+ return getObjectField(env, object, "value");
+ }
+
+ private:
+ JNIEnv *m_env;
+ jobject m_object;
+ public:
+ /*!
+ Creates a new reference.
+
+ @param env A JNIEnv.
+ */
+ Reference(JNIEnv *env);
+
+ /*!
+ Creates a new reference.
+
+ @param env A JNIEnv.
+ @param object A com.artifex.gsjava.util.Reference or NULL if one
+ should be created.
+ */
+ Reference(JNIEnv *env, jobject object);
+ ~Reference();
+
+ inline jobject object()
+ {
+ return m_object;
+ }
+
+ inline jobject value()
+ {
+ return getValueField(m_env, m_object);
+ }
+
+ inline jboolean booleanValue()
+ {
+ jobject val = value();
+ return val ? toBoolean(m_env, val) : JNI_FALSE;
+ }
+
+ inline jbyte byteValue()
+ {
+ jobject val = value();
+ return val ? toByte(m_env, val) : 0;
+ }
+
+ inline jchar charValue()
+ {
+ jobject val = value();
+ return val ? toChar(m_env, val) : 0;
+ }
+
+ inline jshort shortValue()
+ {
+ jobject val = value();
+ return val ? toShort(m_env, val) : 0;
+ }
+
+ inline jint intValue()
+ {
+ jobject val = value();
+ return val ? toInt(m_env, val) : 0;
+ }
+
+ inline jlong longValue()
+ {
+ jobject val = value();
+ return val ? toLong(m_env, val) : 0LL;
+ }
+
+ inline jfloat floatValue()
+ {
+ jobject val = value();
+ return val ? toFloat(m_env, val) : 0.0f;
+ }
+
+ inline jdouble doubleValue()
+ {
+ jobject val = value();
+ return val ? toDouble(m_env, val) : 0.0;
+ }
+
+ inline void set(jobject value)
+ {
+ setValueField(m_env, m_object, value);
+ }
+
+ inline void set(jboolean value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jbyte value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jshort value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jint value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jlong value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jfloat value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+
+ inline void set(jdouble value)
+ {
+ set(toWrapperType(m_env, value));
+ }
+ };
+
+}
diff --git a/demos/python/gsapiwrap.py b/demos/python/gsapiwrap.py
deleted file mode 100755
index 0ef0bb08..00000000
--- a/demos/python/gsapiwrap.py
+++ /dev/null
@@ -1,699 +0,0 @@
-#! /usr/bin/env python3
-
-'''
-Use Swig to build wrappers for gsapi.
-
-Example usage:
-
- Note that we use mupdf's scripts/jlib.py, and assume that there is a mupdf
- checkout in the parent directory of the ghostpdl checkout - see 'import
- jlib' below.
-
- ./toolbin/gsapiwrap.py --python -l -0 -1 -t
- Build python wrapper for gsapi and run simple test.
-
- ./toolbin/gsapiwrap.py --csharp -l -0 -1 -t
- Build C# wrapper for gsapi and run simple test.
-
-Args:
-
- -c:
- Clean language-specific out-dir.
-
- -l:
- Build libgs.so (by running make).
-
- -0:
- Run swig to generate language-specific files.
-
- -1:
- Generate language wrappers by compiling/linking the files generated by
- -0.
-
- --csharp:
- Generate C# wrappers (requires Mono on Linux). Should usually be first
- param.
-
- --python
- Generate Python wrappers. Should usually be first param.
-
- --swig <swig>
- Set location of swig binary.
-
- -t
- Run simple test of language wrappers generated by -1.
-
-Status:
- As of 2020-05-22:
- Some python wrappers seem to work ok.
-
- C# wrappers are not implemented for gsapi_set_poll() and
- gsapi_set_stdio().
-'''
-
-import os
-import re
-import sys
-import textwrap
-
-import jlib
-
-
-def devpython_info():
- '''
- Use python3-config to find libpython.so and python-dev include path etc.
- '''
- python_configdir = jlib.system( 'python3-config --configdir', out='return')
- libpython_so = os.path.join(
- python_configdir.strip(),
- f'libpython{sys.version_info[0]}.{sys.version_info[1]}.so',
- )
- assert os.path.isfile( libpython_so), f'cannot find libpython_so={libpython_so}'
-
- python_includes = jlib.system( 'python3-config --includes', out='return')
- python_includes = python_includes.strip()
- return python_includes, libpython_so
-
-def swig_version( swig='swig'):
- t = jlib.system( f'{swig} -version', out='return')
- m = re.search( 'SWIG Version ([0-9]+)[.]([0-9]+)[.]([0-9]+)', t)
- assert m
- swig_major = int( m.group(1))
- return swig_major
-
-
-dir_ghostpdl = os.path.abspath( f'{__file__}/../../') + '/'
-
-
-def out_dir( language):
- if language == 'python':
- return 'gsapiwrap/python/'
- if language == 'csharp':
- return 'gsapiwrap/csharp/'
- assert 0
-
-def out_so( language):
- '''
- Returns name of .so that implements language-specific wrapper. I think
- these names have to match what the language runtime requires.
-
- For python, Swig generates a module foo.py which does 'import _foo'.
-
- Similarly C# assumes a file called 'libfoo.so'.
- '''
- if language == 'python':
- return f'{out_dir(language)}_gsapi.so'
- if language == 'csharp':
- return f'{out_dir(language)}libgsapi.so'
- assert 0
-
-def lib_gs_info():
- return f'{dir_ghostpdl}sodebugbin/libgs.so', 'make sodebug'
- return f'{dir_ghostpdl}sobin/libgs.so', 'make so'
-
-def lib_gs():
- '''
- Returns name of the gs shared-library.
- '''
- return lib_gs_info()[0]
-
-
-def swig_i( swig, language):
- '''
- Returns text for a swig .i file for psi/iapi.h.
- '''
- swig_major = swig_version( swig)
-
-
- # We need to redeclare or wrap some functions, e.g. to add OUTPUT
- # annotations. We use #define, %ignore and #undef to hide the original
- # declarations in the .h file.
- #
- fns_redeclare = (
- 'gsapi_run_file',
- 'gsapi_run_string',
- 'gsapi_run_string_begin',
- 'gsapi_run_string_continue',
- 'gsapi_run_string_end',
- 'gsapi_run_string_with_length',
- 'gsapi_set_poll',
- 'gsapi_set_poll_with_handle',
- 'gsapi_set_stdio',
- 'gsapi_set_stdio_with_handle',
- 'gsapi_new_instance',
- )
-
-
- swig_i_text = textwrap.dedent(f'''
- %module(directors="1") gsapi
-
- %include cpointer.i
- %pointer_functions(int, pint);
-
- // This seems to be necessary to make csharp handle OUTPUT args.
- //
- %include typemaps.i
-
- // For gsapi_init_with_args().
- %include argcargv.i
-
- %include cstring.i
-
- // Include type information in python doc strings. If we have
- // swig-4, we can propogate comments from the C api instead, which
- // is preferred.
- //
- {'%feature("autodoc", "3");' if swig_major < 4 else ''}
-
- %{{
- #include "psi/iapi.h"
- //#include "base/gserrors.h"
-
- // Define wrapper functions that present a modified API that
- // swig can cope with.
- //
-
- // Swig cannot handle void** out-param.
- //
- static void* new_instance( void* caller_handle, int* out)
- {{
- void* ret = NULL;
- *out = gsapi_new_instance( &ret, caller_handle);
- printf( "gsapi_new_instance() returned *out=%i ret=%p\\n", *out, ret);
- fflush( stdout);
- return ret;
- }}
-
- // Swig cannot handle (const char* str, int strlen) args.
- //
- static int run_string_continue(void *instance, const char *str, int user_errors, int *pexit_code) {{
-
- return gsapi_run_string_continue( instance, str, strlen(str), user_errors, pexit_code);
- }}
- %}}
-
- // Strip gsapi_ prefix from all generated names.
- //
- %rename("%(strip:[gsapi_])s") "";
-
- // Tell Swig about gsapi_get_default_device_list()'s out-params, so
- // it adds them to the returned object.
- //
- // I think the '(void) *$1' will ensure that swig code doesn't
- // attempt to free() the returned string.
- //
- {'%cstring_output_allocate_size(char **list, int *listlen, (void) *$1);' if language == 'python' else ''}
-
- // Tell swig about the (argc,argv) args in gsapi_init_with_args().
- //
- %apply (int ARGC, char **ARGV) {{ (int argc, char **argv) }}
-
- // Support for wrapping various functions that take function
- // pointer args. For each, we define a wrapper function that,
- // instead of having function pointer args, takes a class with
- // virtual methods. This allows swig to wrap things - python/c# etc
- // can create a derived class that implements these virtual methods
- // in the python/c# world.
- //
-
- // Wrap gsapi_set_stdio_with_handle().
- //
- %feature("director") set_stdio_class;
-
- %inline {{
- struct set_stdio_class {{
-
- virtual int stdin_fn( char* buf, int len) = 0;
- virtual int stdout_fn( const char* buf, int len) = 0;
- virtual int stderr_fn( const char* buf, int len) = 0;
-
- static int stdin_fn_wrap( void *caller_handle, char *buf, int len) {{
- return ((set_stdio_class*) caller_handle)->stdin_fn(buf, len);
- }}
- static int stdout_fn_wrap( void *caller_handle, const char *buf, int len) {{
- return ((set_stdio_class*) caller_handle)->stdout_fn(buf, len);
- }}
- static int stderr_fn_wrap( void *caller_handle, const char *buf, int len) {{
- return ((set_stdio_class*) caller_handle)->stderr_fn(buf, len);
- }}
-
- virtual ~set_stdio_class() {{}}
- }};
-
- int set_stdio_with_class( void *instance, set_stdio_class* class_) {{
- return gsapi_set_stdio_with_handle(
- instance,
- set_stdio_class::stdin_fn_wrap,
- set_stdio_class::stdout_fn_wrap,
- set_stdio_class::stderr_fn_wrap,
- (void*) class_
- );
- }}
-
-
- }}
-
- // Wrap gsapi_set_poll().
- //
- %feature("director") set_poll_class;
-
- %inline {{
- struct set_poll_class {{
- virtual int poll_fn() = 0;
-
- static int poll_fn_wrap( void* caller_handle) {{
- return ((set_poll_class*) caller_handle)->poll_fn();
- }}
-
- virtual ~set_poll_class() {{}}
- }};
-
- int set_poll_with_class( void* instance, set_poll_class* class_) {{
- return gsapi_set_poll_with_handle(
- instance,
- set_poll_class::poll_fn_wrap,
- (void*) class_
- );
- }}
-
- }}
-
- // For functions that we re-declare (typically to specify OUTPUT on
- // one or more args), use a macro to rename the declaration in the
- // header file and tell swig to ignore these renamed declarations.
- //
- ''')
-
- for fn in fns_redeclare:
- swig_i_text += f'#define {fn} {fn}0\n'
-
- for fn in fns_redeclare:
- swig_i_text += f'%ignore {fn}0;\n'
-
- swig_i_text += textwrap.dedent(f'''
- #include "psi/iapi.h"
- //#include "base/gserrors.h"
- ''')
-
- for fn in fns_redeclare:
- swig_i_text += f'#undef {fn}\n'
-
-
- swig_i_text += textwrap.dedent(f'''
- // Tell swig about our wrappers and altered declarations.
- //
-
- // Use swig's OUTPUT annotation for out-parameters.
- //
- int gsapi_run_file(void *instance, const char *file_name, int user_errors, int *OUTPUT);
- int gsapi_run_string_begin(void *instance, int user_errors, int *OUTPUT);
- int gsapi_run_string_end(void *instance, int user_errors, int *OUTPUT);
- //int gsapi_run_string_with_length(void *instance, const char *str, unsigned int length, int user_errors, int *OUTPUT);
- int gsapi_run_string(void *instance, const char *str, int user_errors, int *OUTPUT);
-
- // Declare functions defined above that we want swig to wrap. These
- // don't have the gsapi_ prefix, so that they can internally call
- // the wrapped gsapi_*() function. [We've told swig to strip the
- // gsapi_ prefix on generated functions anyway, so this doesn't
- // afffect the generated names.]
- //
- static int run_string_continue(void *instance, const char *str, int user_errors, int *OUTPUT);
- static void* new_instance(void* caller_handle, int* OUTPUT);
- ''')
-
- if language == 'python':
- swig_i_text += textwrap.dedent(f'''
-
- // Define python code that is needed to handle functions with
- // function-pointer args.
- //
- %pythoncode %{{
-
- set_stdio_g = None
- def set_stdio( instance, stdin, stdout, stderr):
- class derived( set_stdio_class):
- def stdin_fn( self):
- return stdin()
- def stdout_fn( self, text, len):
- return stdout( text, len)
- def stderr_fn( self, text, len):
- return stderr( text)
-
- global set_stdio_g
- set_stdio_g = derived()
- return set_stdio_with_class( instance, set_stdio_g)
-
- set_poll_g = None
- def set_poll( instance, fn):
- class derived( set_poll_class):
- def poll_fn( self):
- return fn()
- global set_poll_g
- set_poll_g = derived()
- return set_poll_with_class( instance, set_poll_g)
- %}}
- ''')
-
- return swig_i_text
-
-
-
-def run_swig( swig, language):
- '''
- Runs swig using a generated .i file.
-
- The .i file modifies the gsapi API in places to allow specification of
- out-parameters that swig understands - e.g. void** OUTPUT doesn't work.
- '''
- os.makedirs( out_dir(language), exist_ok=True)
- swig_major = swig_version( swig)
-
- swig_i_text = swig_i( swig, language)
- swig_i_filename = f'{out_dir(language)}iapi.i'
- jlib.update_file( swig_i_text, swig_i_filename)
-
- out_cpp = f'{out_dir(language)}gsapi.cpp'
-
- if language == 'python':
- out_lang = f'{out_dir(language)}gsapi.py'
- elif language == 'csharp':
- out_lang = f'{out_dir(language)}gsapi.cs'
- else:
- assert 0
-
- out_files = (out_cpp, out_lang)
-
- doxygen_arg = ''
- if swig_major >= 4 and language == 'python':
- doxygen_arg = '-doxygen'
-
- extra = ''
- if language == 'csharp':
- # Tell swig to put all generated csharp code into a single file.
- extra = f'-outfile gsapi.cs'
-
- command = (textwrap.dedent(f'''
- {swig}
- -Wall
- -c++
- -{language}
- {doxygen_arg}
- -module gsapi
- -outdir {out_dir(language)}
- -o {out_cpp}
- {extra}
- -includeall
- -I{dir_ghostpdl}
- -ignoremissing
- {swig_i_filename}
- ''').strip().replace( '\n', ' \\\n')
- )
-
- jlib.build(
- (swig_i_filename,),
- out_files,
- command,
- prefix=' ',
- )
-
-
-def main( argv):
-
- swig = 'swig'
- language = 'python'
-
- args = jlib.Args( sys.argv[1:])
- while 1:
- try:
- arg = args.next()
- except StopIteration:
- break
-
- if 0:
- pass
-
- elif arg == '-c':
- jlib.system( f'rm {out_dir(language)}* || true', verbose=1, prefix=' ')
-
- elif arg == '-l':
- command = lib_gs_info()[1]
- jlib.system( command, verbose=1, prefix=' ')
-
- elif arg == '-0':
- run_swig( swig, language)
-
- elif arg == '-1':
-
- libs = [lib_gs()]
- includes = [dir_ghostpdl]
- file_cpp = f'{out_dir(language)}gsapi.cpp'
-
- if language == 'python':
- python_includes, libpython_so = devpython_info()
- libs.append( libpython_so)
- includes.append( python_includes)
-
- includes_text = ''
- for i in includes:
- includes_text += f' -I{i}'
- command = textwrap.dedent(f'''
- g++
- -g
- -Wall -W
- -o {out_so(language)}
- -fPIC
- -shared
- {includes_text}
- {jlib.link_l_flags(libs)}
- {file_cpp}
- ''').strip().replace( '\n', ' \\\n')
- jlib.build(
- (file_cpp, lib_gs(), 'psi/iapi.h'),
- (out_so(language),),
- command,
- prefix=' ',
- )
-
- elif arg == '--csharp':
- language = 'csharp'
-
- elif arg == '--python':
- language = 'python'
-
- elif arg == '--swig':
- swig = args.next()
-
- elif arg == '-t':
-
- if language == 'python':
- text = textwrap.dedent('''
- #!/usr/bin/env python3
-
- import os
- import sys
-
- import gsapi
-
- gsapi.gs_error_Quit = -101
-
- def main():
- minst, code = gsapi.new_instance(None)
- print( f'minst={minst} code={code}')
-
- if 1:
- def stdin_local(len):
- # Not sure whether this is right.
- return sys.stdin.read(len)
- def stdout_local(text, l):
- sys.stdout.write(text[:l])
- return l
- def stderr_local(text, l):
- sys.stderr.write(text[:l])
- return l
- gsapi.set_stdio( minst, None, stdout_local, stderr_local);
-
- if 1:
- def poll_fn():
- return 0
- gsapi.set_poll(minst, poll_fn)
- if 1:
- s = 'display x11alpha x11 bbox'
- gsapi.set_default_device_list( minst, s, len(s))
-
- e, text = gsapi.get_default_device_list( minst)
- print( f'gsapi.get_default_device_list() returned e={e} text={text!r}')
-
- out = 'out.pdf'
- if os.path.exists( out):
- os.remove( out)
- assert not os.path.exists( out)
-
- gsargv = ['']
- gsargv += f'-dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -sOutputFile={out} contrib/pcl3/ps/levels-test.ps'.split()
- print( f'gsargv={gsargv}')
- code = gsapi.set_arg_encoding(minst, gsapi.GS_ARG_ENCODING_UTF8)
- if code == 0:
- code = gsapi.init_with_args(minst, gsargv)
-
- code, exit_code = gsapi.run_string_begin( minst, 0)
- print( f'gsapi.run_string_begin() returned code={code} exit_code={exit_code}')
- assert code == 0
- assert exit_code == 0
-
- gsapi.run_string
-
- code1 = gsapi.exit(minst)
- if (code == 0 or code == gsapi.gs_error_Quit):
- code = code1
- gsapi.delete_instance(minst)
- assert os.path.isfile( out)
- if code == 0 or code == gsapi.gs_error_Quit:
- return 0
- return 1
-
- if __name__ == '__main__':
- code = main()
- assert code == 0
- sys.exit( code)
- ''')
- text = text[1:] # skip leading \n.
- test_py = f'{out_dir(language)}test.py'
- jlib.update_file( text, test_py)
- os.chmod( test_py, 0o744)
-
- jlib.system(
- f'LD_LIBRARY_PATH={os.path.abspath( f"{lib_gs()}/..")}'
- f' PYTHONPATH={out_dir(language)}'
- f' {test_py}'
- ,
- verbose = 1,
- prefix=' ',
- )
-
- elif language == 'csharp':
- # See: https://github.com/swig/swig/blob/master/Lib/csharp/typemaps.i
- #
- text = textwrap.dedent('''
- using System;
- public class runme {
- static void Main() {
- int code;
- SWIGTYPE_p_void instance;
- Console.WriteLine("hello world");
- instance = gsapi.new_instance(null, out code);
- Console.WriteLine("code is: " + code);
- gsapi.add_control_path(instance, 0, "hello");
- }
- }
- ''')
- test_cs = f'{out_dir(language)}test.cs'
- jlib.update_file( text, test_cs)
- files_in = f'{out_dir(language)}gsapi.cs', test_cs
- file_out = f'{out_dir(language)}test.exe'
- command = f'mono-csc -debug+ -out:{file_out} {" ".join(files_in)}'
- jlib.build( files_in, (file_out,), command, prefix=' ')
-
- ld_library_path = f'{dir_ghostpdl}sobin'
- jlib.system( f'LD_LIBRARY_PATH={ld_library_path} {file_out}', verbose=jlib.log, prefix=' ')
-
- elif arg == '--tt':
- # small swig test case.
- os.makedirs( 'swig-tt', exist_ok=True)
- i = textwrap.dedent(f'''
- %include cpointer.i
- %include cstring.i
- %feature("autodoc", "3");
- %cstring_output_allocate_size(char **list, int *listlen, (void) *$1);
- %inline {{
- static inline int gsapi_get_default_device_list(void *instance, char **list, int *listlen)
- {{
- *list = (char*) "hello world";
- *listlen = 6;
- return 0;
- }}
- }}
- ''')
- jlib.update_file(i, 'swig-tt/tt.i')
- jlib.system('swig -c++ -python -module tt -outdir swig-tt -o swig-tt/tt.cpp swig-tt/tt.i', verbose=1)
- p = textwrap.dedent(f'''
- #!/usr/bin/env python3
- import tt
- print( tt.gsapi_get_default_device_list(None))
- ''')[1:]
- jlib.update_file( p, 'swig-tt/test.py')
- python_includes, python_so = devpython_info()
- includes = f'-I {python_includes}'
- link_flags = jlib.link_l_flags( [python_so])
- jlib.system( f'g++ -shared -fPIC {includes} {link_flags} -o swig-tt/_tt.so swig-tt/tt.cpp', verbose=1)
- jlib.system( f'cd swig-tt; python3 test.py', verbose=1)
-
- elif arg == '-T':
- # Very simple test that we can create c# wrapper for trivial code.
- os.makedirs( 'swig-cs-test', exist_ok=True)
- example_cpp = textwrap.dedent('''
- #include <time.h>
- double My_variable = 3.0;
-
- int fact(int n) {
- if (n <= 1) return 1;
- else return n*fact(n-1);
- }
-
- int my_mod(int x, int y) {
- return (x%y);
- }
-
- char *get_time()
- {
- time_t ltime;
- time(&ltime);
- return ctime(&ltime);
- }
- ''')
- jlib.update_file( example_cpp, 'swig-cs-test/example.cpp')
-
- example_i = textwrap.dedent('''
- %module example
- %{
- /* Put header files here or function declarations like below */
- extern double My_variable;
- extern int fact(int n);
- extern int my_mod(int x, int y);
- extern char *get_time();
- %}
-
- extern double My_variable;
- extern int fact(int n);
- extern int my_mod(int x, int y);
- extern char *get_time();
- ''')
- jlib.update_file( example_i, 'swig-cs-test/example.i')
-
- runme_cs = textwrap.dedent('''
- using System;
- public class runme {
- static void Main() {
- Console.WriteLine(example.My_variable);
- Console.WriteLine(example.fact(5));
- Console.WriteLine(example.get_time());
- }
- }
- ''')
- jlib.update_file( runme_cs, 'swig-cs-test/runme.cs')
- jlib.system( 'g++ -g -fPIC -shared -o swig-cs-test/libfoo.so swig-cs-test/example.cpp', verbose=1)
- jlib.system( 'swig -c++ -csharp -module example -outdir swig-cs-test -o swig-cs-test/example_wrap.cpp -outfile example.cs swig-cs-test/example.i', verbose=1)
- jlib.system( 'g++ -g -fPIC -shared -L swig-cs-test -l foo swig-cs-test/example_wrap.cpp -o swig-cs-test/libexample.so', verbose=1)
- jlib.system( 'cd swig-cs-test; mono-csc -out:runme.exe example.cs runme.cs', verbose=1)
- jlib.system( 'cd swig-cs-test; LD_LIBRARY_PATH=`pwd` ./runme.exe', verbose=1)
- jlib.system( 'ls -l swig-cs-test', verbose=1)
-
-
- else:
- raise Exception( f'unrecognised arg: {arg}')
-
-if __name__ == '__main__':
- try:
- main( sys.argv)
- except Exception as e:
- jlib.exception_info( out=sys.stdout)
- sys.exit(1)
diff --git a/demos/python/jlib.py b/demos/python/jlib.py
deleted file mode 100644
index 20506c38..00000000
--- a/demos/python/jlib.py
+++ /dev/null
@@ -1,1355 +0,0 @@
-from __future__ import print_function
-
-import codecs
-import inspect
-import io
-import os
-import shutil
-import subprocess
-import sys
-import time
-import traceback
-import threading
-
-
-def place( frame_record):
- '''
- Useful debugging function - returns representation of source position of
- caller.
- '''
- filename = frame_record.filename
- line = frame_record.lineno
- function = frame_record.function
- ret = os.path.split( filename)[1] + ':' + str( line) + ':' + function + ':'
- if 0:
- tid = str(threading.currentThread())
- ret = '[' + tid + '] ' + ret
- return ret
-
-
-def expand_nv( text, caller):
- '''
- Returns <text> with special handling of {<expression>} items.
-
- text:
- String containing {<expression>} items.
- caller:
- If an int, the number of frames to step up when looking for file:line
- information or evaluating expressions.
-
- Otherwise should be a frame record as returned by inspect.stack()[].
-
- <expression> is evaluated in <caller>'s context using eval(), and expanded
- to <expression> or <expression>=<value>.
-
- If <expression> ends with '=', this character is removed and we prefix the
- result with <expression>=.
-
- E.g.:
- x = 45
- y = 'hello'
- expand_nv( 'foo {x} {y=}')
- returns:
- foo 45 y=hello
-
- <expression> can also use ':' and '!' to control formatting, like
- str.format().
- '''
- if isinstance( caller, int):
- frame_record = inspect.stack()[ caller]
- else:
- frame_record = caller
- frame = frame_record.frame
- try:
- def get_items():
- '''
- Yields (pre, item), where <item> is contents of next {...} or None,
- and <pre> is preceding text.
- '''
- pos = 0
- pre = ''
- while 1:
- if pos == len( text):
- yield pre, None
- break
- rest = text[ pos:]
- if rest.startswith( '{{') or rest.startswith( '}}'):
- pre += rest[0]
- pos += 2
- elif text[ pos] == '{':
- close = text.find( '}', pos)
- if close < 0:
- raise Exception( 'After "{" at offset %s, cannot find closing "}". text is: %r' % (
- pos, text))
- yield pre, text[ pos+1 : close]
- pre = ''
- pos = close + 1
- else:
- pre += text[ pos]
- pos += 1
-
- ret = ''
- for pre, item in get_items():
- ret += pre
- nv = False
- if item:
- if item.endswith( '='):
- nv = True
- item = item[:-1]
- expression, tail = split_first_of( item, '!:')
- try:
- value = eval( expression, frame.f_globals, frame.f_locals)
- value_text = ('{0%s}' % tail).format( value)
- except Exception as e:
- value_text = '{??Failed to evaluate %r in context %s:%s because: %s??}' % (
- expression,
- frame_record.filename,
- frame_record.lineno,
- e,
- )
- if nv:
- ret += '%s=' % expression
- ret += value_text
-
- return ret
-
- finally:
- del frame
-
-
-class LogPrefixTime:
- def __init__( self, date=False, time_=True, elapsed=False):
- self.date = date
- self.time = time_
- self.elapsed = elapsed
- self.t0 = time.time()
- def __call__( self):
- ret = ''
- if self.date:
- ret += time.strftime( ' %F')
- if self.time:
- ret += time.strftime( ' %T')
- if self.elapsed:
- ret += ' (+%s)' % time_duration( time.time() - self.t0, s_format='%.1f')
- if ret:
- ret = ret.strip() + ': '
- return ret
-
-class LogPrefixFileLine:
- def __call__( self, caller):
- if isinstance( caller, int):
- caller = inspect.stack()[ caller]
- return place( caller) + ' '
-
-class LogPrefixScopes:
- '''
- Internal use only.
- '''
- def __init__( self):
- self.items = []
- def __call__( self):
- ret = ''
- for item in self.items:
- if callable( item):
- item = item()
- ret += item
- return ret
-
-
-class LogPrefixScope:
- '''
- Can be used to insert scoped prefix to log output.
- '''
- def __init__( self, prefix):
- g_log_prefixe_scopes.items.append( prefix)
- def __enter__( self):
- pass
- def __exit__( self, exc_type, exc_value, traceback):
- global g_log_prefix
- g_log_prefixe_scopes.items.pop()
-
-
-g_log_delta = 0
-
-class LogDeltaScope:
- '''
- Can be used to temporarily change verbose level of logging.
-
- E.g to temporarily increase logging:
-
- with jlib.LogDeltaScope(-1):
- ...
- '''
- def __init__( self, delta):
- self.delta = delta
- global g_log_delta
- g_log_delta += self.delta
- def __enter__( self):
- pass
- def __exit__( self, exc_type, exc_value, traceback):
- global g_log_delta
- g_log_delta -= self.delta
-
-# Special item that can be inserted into <g_log_prefixes> to enable
-# temporary addition of text into log prefixes.
-#
-g_log_prefixe_scopes = LogPrefixScopes()
-
-# List of items that form prefix for all output from log().
-#
-g_log_prefixes = []
-
-
-def log_text( text=None, caller=1, nv=True):
- '''
- Returns log text, prepending all lines with text from g_log_prefixes.
-
- text:
- The text to output. Each line is prepended with prefix text.
- caller:
- If an int, the number of frames to step up when looking for file:line
- information or evaluating expressions.
-
- Otherwise should be a frame record as returned by inspect.stack()[].
- nv:
- If true, we expand {...} in <text> using expand_nv().
- '''
- if isinstance( caller, int):
- caller += 1
- prefix = ''
- for p in g_log_prefixes:
- if callable( p):
- if isinstance( p, LogPrefixFileLine):
- p = p(caller)
- else:
- p = p()
- prefix += p
-
- if text is None:
- return prefix
-
- if nv:
- text = expand_nv( text, caller)
-
- if text.endswith( '\n'):
- text = text[:-1]
- lines = text.split( '\n')
-
- text = ''
- for line in lines:
- text += prefix + line + '\n'
- return text
-
-
-
-s_log_levels_cache = dict()
-s_log_levels_items = []
-
-def log_levels_find( caller):
- if not s_log_levels_items:
- return 0
-
- tb = traceback.extract_stack( None, 1+caller)
- if len(tb) == 0:
- return 0
- filename, line, function, text = tb[0]
-
- key = function, filename, line,
- delta = s_log_levels_cache.get( key)
-
- if delta is None:
- # Calculate and populate cache.
- delta = 0
- for item_function, item_filename, item_delta in s_log_levels_items:
- if item_function and not function.startswith( item_function):
- continue
- if item_filename and not filename.startswith( item_filename):
- continue
- delta = item_delta
- break
-
- s_log_levels_cache[ key] = delta
-
- return delta
-
-
-def log_levels_add( delta, filename_prefix, function_prefix):
- '''
- log() calls from locations with filenames starting with <filename_prefix>
- and/or function names starting with <function_prefix> will have <delta>
- added to their level.
-
- Use -ve delta to increase verbosity from particular filename or function
- prefixes.
- '''
- log( 'adding level: {filename_prefix=!r} {function_prefix=!r}')
-
- # Sort in reverse order so that long functions and filename specs come
- # first.
- #
- s_log_levels_items.append( (function_prefix, filename_prefix, delta))
- s_log_levels_items.sort( reverse=True)
-
-
-def log( text, level=0, caller=1, nv=True, out=None):
- '''
- Writes log text, with special handling of {<expression>} items in <text>
- similar to python3's f-strings.
-
- text:
- The text to output.
- caller:
- How many frames to step up to get caller's context when evaluating
- file:line information and/or expressions. Or frame record as returned
- by inspect.stack()[].
- nv:
- If true, we expand {...} in <text> using expand_nv().
- out:
- Where to send output. If None we use sys.stdout.
-
- <expression> is evaluated in our caller's context (<n> stack frames up)
- using eval(), and expanded to <expression> or <expression>=<value>.
-
- If <expression> ends with '=', this character is removed and we prefix the
- result with <expression>=.
-
- E.g.:
- x = 45
- y = 'hello'
- expand_nv( 'foo {x} {y=}')
- returns:
- foo 45 y=hello
-
- <expression> can also use ':' and '!' to control formatting, like
- str.format().
- '''
- if out is None:
- out = sys.stdout
- level += g_log_delta
- if isinstance( caller, int):
- caller += 1
- level += log_levels_find( caller)
- if level <= 0:
- text = log_text( text, caller, nv=nv)
- out.write( text)
- out.flush()
-
-
-def log0( text, caller=1, nv=True, out=None):
- '''
- Most verbose log. Same as log().
- '''
- log( text, level=0, caller=caller+1, nv=nv, out=out)
-
-def log1( text, caller=1, nv=True, out=None):
- log( text, level=1, caller=caller+1, nv=nv, out=out)
-
-def log2( text, caller=1, nv=True, out=None):
- log( text, level=2, caller=caller+1, nv=nv, out=out)
-
-def log3( text, caller=1, nv=True, out=None):
- log( text, level=3, caller=caller+1, nv=nv, out=out)
-
-def log4( text, caller=1, nv=True, out=None):
- log( text, level=4, caller=caller+1, nv=nv, out=out)
-
-def log5( text, caller=1, nv=True, out=None):
- '''
- Least verbose log.
- '''
- log( text, level=5, caller=caller+1, nv=nv, out=out)
-
-def logx( text, caller=1, nv=True, out=None):
- '''
- Does nothing, useful when commenting out a log().
- '''
- pass
-
-
-def log_levels_add_env( name='JLIB_log_levels'):
- '''
- Added log levels encoded in an environmental variable.
- '''
- t = os.environ.get( name)
- if t:
- for ffll in t.split( ','):
- ffl, delta = ffll.split( '=', 1)
- delta = int( delta)
- ffl = ffl.split( ':')
- if 0:
- pass
- elif len( ffl) == 1:
- filename = ffl
- function = None
- elif len( ffl) == 2:
- filename, function = ffl
- else:
- assert 0
- log_levels_add( delta, filename, function)
-
-
-def strpbrk( text, substrings):
- '''
- Finds first occurrence of any item in <substrings> in <text>.
-
- Returns (pos, substring) or (len(text), None) if not found.
- '''
- ret_pos = len( text)
- ret_substring = None
- for substring in substrings:
- pos = text.find( substring)
- if pos >= 0 and pos < ret_pos:
- ret_pos = pos
- ret_substring = substring
- return ret_pos, ret_substring
-
-
-def split_first_of( text, substrings):
- '''
- Returns (pre, post), where <pre> doesn't contain any item in <substrings>
- and <post> is empty or starts with an item in <substrings>.
- '''
- pos, _ = strpbrk( text, substrings)
- return text[ :pos], text[ pos:]
-
-
-
-log_levels_add_env()
-
-
-def force_line_buffering():
- '''
- Ensure sys.stdout and sys.stderr are line-buffered. E.g. makes things work
- better if output is piped to a file via 'tee'.
-
- Returns original out,err streams.
- '''
- stdout0 = sys.stdout
- stderr0 = sys.stderr
- sys.stdout = os.fdopen( os.dup( sys.stdout.fileno()), 'w', 1)
- sys.stderr = os.fdopen( os.dup( sys.stderr.fileno()), 'w', 1)
- return stdout0, stderr0
-
-
-def exception_info( exception=None, limit=None, out=None, prefix='', oneline=False):
- '''
- General replacement for traceback.* functions that print/return information
- about exceptions. This function provides a simple way of getting the
- functionality provided by these traceback functions:
-
- traceback.format_exc()
- traceback.format_exception()
- traceback.print_exc()
- traceback.print_exception()
-
- Returns:
- A string containing description of specified exception and backtrace.
-
- Inclusion of outer frames:
- We improve upon traceback.* in that we also include stack frames above
- the point at which an exception was caught - frames from the top-level
- <module> or thread creation fn to the try..catch block, which makes
- backtraces much more useful.
-
- Google 'sys.exc_info backtrace incomplete' for more details.
-
- We deliberately leave a slightly curious pair of items in the backtrace
- - the point in the try: block that ended up raising an exception, and
- the point in the associated except: block from which we were called.
-
- For clarity, we insert an empty frame in-between these two items, so
- that one can easily distinguish the two parts of the backtrace.
-
- So the backtrace looks like this:
-
- root (e.g. <module> or /usr/lib/python2.7/threading.py:778:__bootstrap():
- ...
- file:line in the except: block where the exception was caught.
- ::(): marker
- file:line in the try: block.
- ...
- file:line where the exception was raised.
-
- The items after the ::(): marker are the usual items that traceback.*
- shows for an exception.
-
- Also the backtraces that are generated are more concise than those provided
- by traceback.* - just one line per frame instead of two - and filenames are
- output relative to the current directory if applicatble. And one can easily
- prefix all lines with a specified string, e.g. to indent the text.
-
- Returns a string containing backtrace and exception information, and sends
- returned string to <out> if specified.
-
- exception:
- None, or a (type, value, traceback) tuple, e.g. from sys.exc_info(). If
- None, we call sys.exc_info() and use its return value.
- limit:
- None or maximum number of stackframes to output.
- out:
- None or callable taking single <text> parameter or object with a
- 'write' member that takes a single <text> parameter.
- prefix:
- Used to prefix all lines of text.
- '''
- if exception is None:
- exception = sys.exc_info()
- etype, value, tb = exception
-
- if sys.version_info[0] == 2:
- out2 = io.BytesIO()
- else:
- out2 = io.StringIO()
- try:
-
- frames = []
-
- # Get frames above point at which exception was caught - frames
- # starting at top-level <module> or thread creation fn, and ending
- # at the point in the catch: block from which we were called.
- #
- # These frames are not included explicitly in sys.exc_info()[2] and are
- # also omitted by traceback.* functions, which makes for incomplete
- # backtraces that miss much useful information.
- #
- for f in reversed(inspect.getouterframes(tb.tb_frame)):
- ff = f[1], f[2], f[3], f[4][0].strip()
- frames.append(ff)
-
- if 1:
- # It's useful to see boundary between upper and lower frames.
- frames.append( None)
-
- # Append frames from point in the try: block that caused the exception
- # to be raised, to the point at which the exception was thrown.
- #
- # [One can get similar information using traceback.extract_tb(tb):
- # for f in traceback.extract_tb(tb):
- # frames.append(f)
- # ]
- for f in inspect.getinnerframes(tb):
- ff = f[1], f[2], f[3], f[4][0].strip()
- frames.append(ff)
-
- cwd = os.getcwd() + os.sep
- if oneline:
- if etype and value:
- # The 'exception_text' variable below will usually be assigned
- # something like '<ExceptionType>: <ExceptionValue>', unless
- # there was no explanatory text provided (e.g. "raise Exception()").
- # In this case, str(value) will evaluate to ''.
- exception_text = traceback.format_exception_only(etype, value)[0].strip()
- filename, line, fnname, text = frames[-1]
- if filename.startswith(cwd):
- filename = filename[len(cwd):]
- if not str(value):
- # The exception doesn't have any useful explanatory text
- # (for example, maybe it was raised by an expression like
- # "assert <expression>" without a subsequent comma). In
- # the absence of anything more helpful, print the code that
- # raised the exception.
- exception_text += ' (%s)' % text
- line = '%s%s at %s:%s:%s()' % (prefix, exception_text, filename, line, fnname)
- out2.write(line)
- else:
- out2.write( '%sBacktrace:\n' % prefix)
- for frame in frames:
- if frame is None:
- out2.write( '%s ^except raise:\n' % prefix)
- continue
- filename, line, fnname, text = frame
- if filename.startswith( cwd):
- filename = filename[ len(cwd):]
- if filename.startswith( './'):
- filename = filename[ 2:]
- out2.write( '%s %s:%s:%s(): %s\n' % (
- prefix, filename, line, fnname, text))
-
- if etype and value:
- out2.write( '%sException:\n' % prefix)
- lines = traceback.format_exception_only( etype, value)
- for line in lines:
- out2.write( '%s %s' % ( prefix, line))
-
- text = out2.getvalue()
-
- # Write text to <out> if specified.
- out = getattr( out, 'write', out)
- if callable( out):
- out( text)
- return text
-
- finally:
- # clear things to avoid cycles.
- exception = None
- etype = None
- value = None
- tb = None
- frames = None
-
-
-def number_sep( s):
- '''
- Simple number formatter, adds commas in-between thousands. <s> can
- be a number or a string. Returns a string.
- '''
- if not isinstance( s, str):
- s = str( s)
- c = s.find( '.')
- if c==-1: c = len(s)
- end = s.find('e')
- if end == -1: end = s.find('E')
- if end == -1: end = len(s)
- ret = ''
- for i in range( end):
- ret += s[i]
- if i<c-1 and (c-i-1)%3==0:
- ret += ','
- elif i>c and i<end-1 and (i-c)%3==0:
- ret += ','
- ret += s[end:]
- return ret
-
-assert number_sep(1)=='1'
-assert number_sep(12)=='12'
-assert number_sep(123)=='123'
-assert number_sep(1234)=='1,234'
-assert number_sep(12345)=='12,345'
-assert number_sep(123456)=='123,456'
-assert number_sep(1234567)=='1,234,567'
-
-
-class Stream:
- '''
- Base layering abstraction for streams - abstraction for things like
- sys.stdout to allow prefixing of all output, e.g. with a timestamp.
- '''
- def __init__( self, stream):
- self.stream = stream
- def write( self, text):
- self.stream.write( text)
-
-class StreamPrefix:
- '''
- Prefixes output with a prefix, which can be a string or a callable that
- takes no parameters and return a string.
- '''
- def __init__( self, stream, prefix):
- self.stream = stream
- self.at_start = True
- if callable(prefix):
- self.prefix = prefix
- else:
- self.prefix = lambda : prefix
-
- def write( self, text):
- if self.at_start:
- text = self.prefix() + text
- self.at_start = False
- append_newline = False
- if text.endswith( '\n'):
- text = text[:-1]
- self.at_start = True
- append_newline = True
- text = text.replace( '\n', '\n%s' % self.prefix())
- if append_newline:
- text += '\n'
- self.stream.write( text)
-
- def flush( self):
- self.stream.flush()
-
-
-def debug( text):
- if callable(text):
- text = text()
- print( text)
-
-debug_periodic_t0 = [0]
-def debug_periodic( text, override=0):
- interval = 10
- t = time.time()
- if t - debug_periodic_t0[0] > interval or override:
- debug_periodic_t0[0] = t
- debug(text)
-
-
-def time_duration( seconds, verbose=False, s_format='%i'):
- '''
- Returns string expressing an interval.
-
- seconds:
- The duration in seconds
- verbose:
- If true, return like '4 days 1 hour 2 mins 23 secs', otherwise as
- '4d3h2m23s'.
- s_format:
- If specified, use as printf-style format string for seconds.
- '''
- x = abs(seconds)
- ret = ''
- i = 0
- for div, text in [
- ( 60, 'sec'),
- ( 60, 'min'),
- ( 24, 'hour'),
- ( None, 'day'),
- ]:
- force = ( x == 0 and i == 0)
- if div:
- remainder = x % div
- x = int( x/div)
- else:
- remainder = x
- if not verbose:
- text = text[0]
- if remainder or force:
- if verbose and remainder > 1:
- # plural.
- text += 's'
- if verbose:
- text = ' %s ' % text
- if i == 0:
- remainder = s_format % remainder
- ret = '%s%s%s' % ( remainder, text, ret)
- i += 1
- ret = ret.strip()
- if ret == '':
- ret = '0s'
- if seconds < 0:
- ret = '-%s' % ret
- return ret
-
-assert time_duration( 303333) == '3d12h15m33s'
-assert time_duration( 303333.33, s_format='%.1f') == '3d12h15m33.3s'
-assert time_duration( 303333, verbose=True) == '3 days 12 hours 15 mins 33 secs'
-assert time_duration( 303333.33, verbose=True, s_format='%.1f') == '3 days 12 hours 15 mins 33.3 secs'
-
-assert time_duration( 0) == '0s'
-assert time_duration( 0, verbose=True) == '0 sec'
-
-
-def date_time( t=None):
- if t is None:
- t = time.time()
- return time.strftime( "%F-%T", time.gmtime( t))
-
-def stream_prefix_time( stream):
- '''
- Returns StreamPrefix that prefixes lines with time and elapsed time.
- '''
- t_start = time.time()
- def prefix_time():
- return '%s (+%s): ' % (
- time.strftime( '%T'),
- time_duration( time.time() - t_start, s_format='0.1f'),
- )
- return StreamPrefix( stream, prefix_time)
-
-def stdout_prefix_time():
- '''
- Changes sys.stdout to prefix time and elapsed time; returns original
- sys.stdout.
- '''
- ret = sys.stdout
- sys.stdout = stream_prefix_time( sys.stdout)
- return ret
-
-
-def make_stream( out):
- '''
- If <out> already has a .write() member, returns <out>.
-
- Otherwise a stream-like object with a .write() method that writes to <out>.
-
- out:
- Where output is sent.
- If None, output is lost.
- Otherwise if an integer, we do: os.write( out, text)
- Otherwise if callable, we do: out( text)
- Otherwise we assume <out> is python stream or similar already.
- '''
- if getattr( out, 'write', None):
- return out
- class Ret:
- def flush():
- pass
- ret = Ret()
- if out is None:
- ret.write = lambda text: None
- elif isinstance( out, int):
- ret.write = lambda text: os.write( out, text)
- elif callable( out):
- ret.write = out
- else:
- ret.write = lambda text: out.write( text)
- return ret
-
-
-def system_raw(
- command,
- out=None,
- shell=True,
- encoding='latin_1',
- errors='strict',
- buffer_len=-1,
- ):
- '''
- Runs command, writing output to <out> which can be an int fd, a python
- stream or a Stream object.
-
- Args:
- command:
- The command to run.
- out:
- Where output is sent.
- If None, output is lost.
- If -1, output is sent to stdout and stderr.
- Otherwise if an integer, we do: os.write( out, text)
- Otherwise if callable, we do: out( text)
- Otherwise we assume <out> is python stream or similar, and do: out.write(text)
- shell:
- Whether to run command inside a shell (see subprocess.Popen).
- encoding:
- Sepecify the encoding used to translate the command's output
- to characters.
-
- Note that if <encoding> is None and we are being run by python3,
- <out> will be passed bytes, not a string.
-
- Note that latin_1 will never raise a UnicodeDecodeError.
- errors:
- How to handle encoding errors; see docs for codecs module for
- details.
- buffer_len:
- The number of bytes we attempt to read at a time. If -1 we read
- output one line at a time.
-
- Returns:
- subprocess's <returncode>, i.e. -N means killed by signal N, otherwise
- the exit value (e.g. 12 if command terminated with exit(12)).
- '''
- if out == -1:
- stdin = 0
- stdout = 1
- stderr = 2
- else:
- stdin = None
- stdout = subprocess.PIPE
- stderr = subprocess.STDOUT
- child = subprocess.Popen(
- command,
- shell=shell,
- stdin=stdin,
- stdout=stdout,
- stderr=stderr,
- close_fds=True,
- #encoding=encoding - only python-3.6+.
- )
-
- child_out = child.stdout
- if encoding:
- child_out = codecs.getreader( encoding)( child_out, errors)
-
- out = make_stream( out)
-
- if stdout == subprocess.PIPE:
- if buffer_len == -1:
- for line in child_out:
- out.write( line)
- else:
- while 1:
- text = child_out.read( buffer_len)
- if not text:
- break
- out.write( text)
- #decode( lambda : os.read( child_out.fileno(), 100), outfn, encoding)
-
- return child.wait()
-
-if __name__ == '__main__':
-
- if os.getenv( 'jtest_py_system_raw_test') == '1':
- out = io.StringIO()
- system_raw(
- 'jtest_py_system_raw_test=2 python jlib.py',
- sys.stdout,
- encoding='utf-8',
- #'latin_1',
- errors='replace',
- )
- print( repr( out.getvalue()))
-
- elif os.getenv( 'jtest_py_system_raw_test') == '2':
- for i in range(256):
- sys.stdout.write( chr(i))
-
-
-def system(
- command,
- verbose=None,
- raise_errors=True,
- out=None,
- prefix=None,
- rusage=False,
- shell=True,
- encoding=None,
- errors='replace',
- buffer_len=-1,
- ):
- '''
- Runs a command like os.system() or subprocess.*, but with more flexibility.
-
- We give control over where the command's output is sent, whether to return
- the output and/or exit code, and whether to raise an exception if the
- command fails.
-
- We also support the use of /usr/bin/time to gather rusage information.
-
- command:
- The command to run.
- verbose:
- If true, we output information about the command that we run, and
- its result.
-
- If callable or something with a .write() method, information is
- sent to <verbose> itself. Otherwise it is sent to <out> (without
- applying <prefix>).
- raise_errors:
- If true, we raise an exception if the command fails, otherwise we
- return the failing error code or zero.
- out:
- Python stream, fd, callable or Stream instance to which output is
- sent.
-
- If <out> is 'return', we buffer the output and return (e,
- <output>). Note that if raise_errors is true, we only return if <e>
- is zero.
-
- If -1, output is sent to stdout and stderr.
- prefix:
- If not None, should be prefix string or callable used to prefix
- all output. [This is for convenience to avoid the need to do
- out=StreamPrefix(...).]
- rusage:
- If true, we run via /usr/bin/time and return rusage string
- containing information on execution. <raise_errors> and
- out='return' are ignored.
- shell:
- Passed to underlying subprocess.Popen() call.
- encoding:
- Sepecify the encoding used to translate the command's output
- to characters. Defaults to utf-8.
- errors:
- How to handle encoding errors; see docs for codecs module
- for details. Defaults to 'replace' so we never raise a
- UnicodeDecodeError.
- buffer_len:
- The number of bytes we attempt to read at a time. If -1 we read
- output one line at a time.
-
- Returns:
- If <rusage> is true, we return the rusage text.
-
- Else if raise_errors is true:
- If the command failed, we raise an exception.
- Else if <out> is 'return' we return the text output from the command.
- Else we return None
-
- Else if <out> is 'return', we return (e, text) where <e> is the
- command's exit code and <text> is the output from the command.
-
- Else we return <e>, the command's exit code.
- '''
- if encoding is None:
- if sys.version_info[0] == 2:
- # python-2 doesn't seem to implement 'replace' properly.
- encoding = None
- errors = None
- else:
- encoding = 'utf-8'
- errors = 'replace'
-
- out_original = out
- if out is None:
- out = sys.stdout
- elif out == 'return':
- # Store the output ourselves so we can return it.
- out = io.StringIO()
- else:
- out = make_stream( out)
-
- if verbose:
- if getattr( verbose, 'write', None):
- pass
- elif callable( verbose):
- verbose = make_stream( verbose)
- else:
- verbose = out
-
- if prefix:
- out = StreamPrefix( out, prefix)
-
- if verbose:
- verbose.write( 'running: %s\n' % command)
-
- if rusage:
- command2 = ''
- command2 += '/usr/bin/time -o ubt-out -f "D=%D E=%D F=%F I=%I K=%K M=%M O=%O P=%P R=%r S=%S U=%U W=%W X=%X Z=%Z c=%c e=%e k=%k p=%p r=%r s=%s t=%t w=%w x=%x C=%C"'
- command2 += ' '
- command2 += command
- system_raw( command2, out, shell, encoding, errors, buffer_len=buffer_len)
- with open('ubt-out') as f:
- rusage_text = f.read()
- #print 'have read rusage output: %r' % rusage_text
- if rusage_text.startswith( 'Command '):
- # Annoyingly, /usr/bin/time appears to write 'Command
- # exited with ...' or 'Command terminated by ...' to the
- # output file before the rusage info if command doesn't
- # exit 0.
- nl = rusage_text.find('\n')
- rusage_text = rusage_text[ nl+1:]
- return rusage_text
- else:
- e = system_raw( command, out, shell, encoding, errors, buffer_len=buffer_len)
-
- if verbose:
- verbose.write( '[returned e=%s]\n' % e)
-
- if raise_errors:
- if e:
- raise Exception( 'command failed: %s' % command)
- if out_original == 'return':
- return out.getvalue()
- return
-
- if out_original == 'return':
- return e, out.getvalue()
- return e
-
-def get_gitfiles( directory, submodules=False):
- '''
- Returns list of all files known to git in <directory>; <directory> must be
- somewhere within a git checkout.
-
- Returned names are all relative to <directory>.
-
- If .git directory, we also create <directory>/jtest-git-files. Otherwise we
- assume a this file already exists.
- '''
- if os.path.isdir( '%s/.git' % directory):
- command = 'cd ' + directory + ' && git ls-files'
- if submodules:
- command += ' --recurse-submodules'
- command += ' > jtest-git-files'
- system( command, verbose=sys.stdout)
-
- with open( '%s/jtest-git-files' % directory, 'r') as f:
- text = f.read()
- ret = text.split( '\n')
- return ret
-
-def get_git_id_raw( directory):
- if not os.path.isdir( '%s/.git' % directory):
- return
- text = system(
- f'cd {directory} && (PAGER= git show --pretty=oneline|head -n 1 && git diff)',
- out='return',
- )
- return text
-
-def get_git_id( directory, allow_none=False):
- '''
- Returns text where first line is '<git-sha> <commit summary>' and remaining
- lines contain output from 'git diff' in <directory>.
-
- directory:
- Root of git checkout.
- allow_none:
- If true, we return None if <directory> is not a git checkout and
- jtest-git-id file does not exist.
- '''
- filename = f'{directory}/jtest-git-id'
- text = get_git_id_raw( directory)
- if text:
- with open( filename, 'w') as f:
- f.write( text)
- elif os.path.isfile( filename):
- with open( filename) as f:
- text = f.read()
- else:
- if not allow_none:
- raise Exception( f'Not in git checkout, and no file {filename}.')
- text = None
- return text
-
-class Args:
- '''
- Iterates over argv items. Does getopt-style splitting of args starting with
- single '-' character.
- '''
- def __init__( self, argv):
- self.argv = argv
- self.pos = 0
- self.pos_sub = None
- def next( self):
- while 1:
- if self.pos >= len(self.argv):
- raise StopIteration()
- arg = self.argv[self.pos]
- if (not self.pos_sub
- and arg.startswith('-')
- and not arg.startswith('--')
- ):
- # Start splitting current arg.
- self.pos_sub = 1
- if self.pos_sub and self.pos_sub >= len(arg):
- # End of '-' sub-arg.
- self.pos += 1
- self.pos_sub = None
- continue
- if self.pos_sub:
- # Return '-' sub-arg.
- ret = arg[self.pos_sub]
- self.pos_sub += 1
- return f'-{ret}'
- # Return normal arg.
- self.pos += 1
- return arg
-
-def update_file( text, filename):
- '''
- Writes <text> to <filename>. Does nothing if contents of <filename> are
- already <text>.
- '''
- try:
- with open( filename) as f:
- text0 = f.read()
- except OSError:
- text0 = None
- if text == text0:
- log( 'Unchanged: ' + filename)
- else:
- log( 'Updating: ' + filename)
- # Write to temp file and rename, to ensure we are atomic.
- filename_temp = f'{filename}-jlib-temp'
- with open( filename_temp, 'w') as f:
- f.write( text)
- os.rename( filename_temp, filename)
-
-
-def mtime( filename, default=0):
- '''
- Returns mtime of file, or <default> if error - e.g. doesn't exist.
- '''
- try:
- return os.path.getmtime( filename)
- except OSError:
- return default
-
-def get_filenames( paths):
- '''
- Yields each file in <paths>, walking any directories.
- '''
- if isinstance( paths, str):
- paths = (paths,)
- for name in paths:
- if os.path.isdir( name):
- for dirpath, dirnames, filenames in os.walk( name):
- for filename in filenames:
- path = os.path.join( dirpath, filename)
- yield path
- else:
- yield name
-
-def remove( path):
- '''
- Removes file or directory, without raising exception if it doesn't exist.
-
- We assert-fail if the path still exists when we return, in case of
- permission problems etc.
- '''
- try:
- os.remove( path)
- except Exception:
- pass
- shutil.rmtree( path, ignore_errors=1)
- assert not os.path.exists( path)
-
-
-# Things for figuring out whether files need updating, using mtimes.
-#
-def newest( names):
- '''
- Returns mtime of newest file in <filenames>. Returns 0 if no file exists.
- '''
- assert isinstance( names, (list, tuple))
- assert names
- ret_t = 0
- ret_name = None
- for filename in get_filenames( names):
- t = mtime( filename)
- if t > ret_t:
- ret_t = t
- ret_name = filename
- return ret_t, ret_name
-
-def oldest( names):
- '''
- Returns mtime of oldest file in <filenames> or 0 if no file exists.
- '''
- assert isinstance( names, (list, tuple))
- assert names
- ret_t = None
- ret_name = None
- for filename in get_filenames( names):
- t = mtime( filename)
- if ret_t is None or t < ret_t:
- ret_t = t
- ret_name = filename
- if ret_t is None:
- ret_t = 0
- return ret_t, ret_name
-
-def update_needed( infiles, outfiles):
- '''
- If any file in <infiles> is newer than any file in <outfiles>, returns
- string description. Otherwise returns None.
- '''
- in_tmax, in_tmax_name = newest( infiles)
- out_tmin, out_tmin_name = oldest( outfiles)
- if in_tmax > out_tmin:
- text = f'{in_tmax_name} is newer than {out_tmin_name}'
- return text
-
-def build(
- infiles,
- outfiles,
- command,
- force_rebuild=False,
- out=None,
- all_reasons=False,
- verbose=True,
- prefix=None,
- ):
- '''
- Ensures that <outfiles> are up to date using enhanced makefile-like
- determinism of dependencies.
-
- Rebuilds <outfiles> by running <command> if we determine that any of them
- are out of date.
-
- infiles:
- Names of files that are read by <command>. Can be a single filename. If
- an item is a directory, we expand to all filenames in the directory's
- tree.
- outfiles:
- Names of files that are written by <command>. Can also be a single
- filename.
- command:
- Command to run.
- force_rebuild:
- If true, we always re-run the command.
- out:
- A callable, passed to jlib.system(). If None, we use jlib.log() with
- our caller's stack record.
- all_reasons:
- If true we check all ways for a build being needed, even if we already
- know a build is needed; this only affects the diagnostic that we
- output.
- verbose:
- Passed to jlib.system().
- prefix:
- Passed to jlib.system().
-
- We compare mtimes of <infiles> and <outfiles>, and we also detect changes
- to the command itself.
-
- If any of infiles are newer than any of outfiles, or <command> is
- different to contents of commandfile '<outfile[0]>.cmd, then truncates
- commandfile and runs <command>. If <command> succeeds we writes <command>
- to commandfile.
- '''
- if isinstance( infiles, str):
- infiles = (infiles,)
- if isinstance( outfiles, str):
- infiles = (outfiles,)
-
- if not out:
- out_frame_record = inspect.stack()[1]
- out = lambda text: log( text, nv=0, caller=out_frame_record)
-
- command_filename = f'{outfiles[0]}.cmd'
-
- reasons = []
-
- if not reasons or all_reasons:
- if force_rebuild:
- reasons.append( 'force_rebuild was specified')
-
- if not reasons or all_reasons:
- try:
- with open( command_filename) as f:
- command0 = f.read()
- except Exception:
- command0 = None
- if command != command0:
- if command0:
- reasons.append( 'command has changed')
- else:
- reasons.append( 'no previous command')
-
- if not reasons or all_reasons:
- reason = update_needed( infiles, outfiles)
- if reason:
- reasons.append( reason)
-
- if not reasons:
- out( 'Already up to date: ' + ' '.join(outfiles))
- return
-
- if out:
- out( 'Rebuilding because %s: %s' % (
- ', and '.join( reasons),
- ' '.join(outfiles),
- ))
-
- # Empty <command_filename) while we run the command so that if command
- # fails but still creates target(s), then next time we will know target(s)
- # are not up to date.
- #
- with open( command_filename, 'w') as f:
- pass
-
- system( command, out=out, verbose=verbose, prefix=prefix)
-
- with open( command_filename, 'w') as f:
- f.write( command)
-
-
-def link_l_flags( sos):
- '''
- Returns flags needed to link with items in <sos>. For each unique item we
- use -L with parent directory, and -l with embedded name (without leading
- 'lib' or trailing '.co').
- '''
- dirs = set()
- names = []
- if isinstance( sos, str):
- sos = (sos,)
- for so in sos:
- dir_ = os.path.dirname( so)
- name = os.path.basename( so)
- assert name.startswith( 'lib')
- assert name.endswith ( '.so')
- name = name[3:-3]
- dirs.add( dir_)
- names.append( name)
- ret = ''
- # Important to use sorted() here, otherwise ordering from set() is
- # arbitrary causing occasional spurious rebuilds by jlib.build().
- for dir_ in sorted(dirs):
- ret += f' -L {dir_}'
- for name in names:
- ret += f' -l {name}'
- return ret