Added unicode support on Windows.

Fixed AL and GLES native stub bindings.
Replaced many GetStringNativeChars usages with a Java implementation.
This commit is contained in:
Ioannis Tsakpinis 2011-08-16 22:17:32 +00:00
parent 3da40143e3
commit 67945fe317
19 changed files with 253 additions and 225 deletions

View file

@ -33,6 +33,8 @@ package org.lwjgl;
import java.lang.reflect.Field;
import java.nio.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
/**
* [INTERNAL USE ONLY]
@ -43,6 +45,16 @@ import java.nio.*;
*/
public final class MemoryUtil {
private static final CharsetEncoder textEncoder;
static {
CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
if ( 1.0f < encoder.maxBytesPerChar() )
encoder = Charset.forName("ISO-8859-1").newEncoder();
textEncoder = encoder;
}
private static final Accessor memUtil;
static {
@ -92,10 +104,6 @@ public final class MemoryUtil {
private MemoryUtil() {
}
public static String wrap(final String test) {
return "MemoryUtil.getAddress(" + test + ")";
}
/**
* Returns the memory address of the specified buffer. [INTERNAL USE ONLY]
*
@ -179,6 +187,66 @@ public final class MemoryUtil {
public static long getAddressSafe(PointerBuffer buffer, int position) { return buffer == null ? 0L : getAddress(buffer, position); }
// --- [ String utilities ] ---
/**
* Returns the specified text as a null-terminated CharBuffer.
*
* @param text the text to encode
*
* @return the encoded text
*/
public static CharBuffer encodeUTF16(final CharSequence text) {
CharBuffer buffer = BufferUtils.createCharBuffer(text.length() + 1);
buffer.append(text).append('\0');
buffer.flip();
return buffer;
}
/**
* Returns the specified text array as a CharBuffer. The CharBuffer is packed
* and each text is null-terminated.
*
* @param text the text array to encode
*
* @return the encoded text
*/
public static CharBuffer encodeUTF16(final CharSequence... text) {
int len = 0;
for ( CharSequence cs : text )
len += cs.length();
final CharBuffer buffer = BufferUtils.createCharBuffer(len + text.length);
for ( CharSequence cs : text )
buffer.append(cs).append('\0');
buffer.flip();
return buffer;
}
/**
* Encodes and null-terminated the specified text and returns a ByteBuffer.
* If text is null, null is returned.
*
* @param text the text to encode
*
* @return the encoded text or null
*
* @see String#getBytes()
*/
public static ByteBuffer encodeASCII(final CharSequence text) {
if ( text == null )
return null;
final ByteBuffer buffer = BufferUtils.createByteBuffer(text.length() + 1);
textEncoder.encode(CharBuffer.wrap(text), buffer, true);
buffer.put((byte)0);
buffer.flip();
return buffer;
}
interface Accessor {
long getAddress(Buffer buffer);

View file

@ -31,6 +31,7 @@
*/
package org.lwjgl;
import java.nio.CharBuffer;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.AccessController;
@ -95,9 +96,15 @@ final class WindowsSysImplementation extends DefaultSysImplementation {
if(!Display.isCreated()) {
initCommonControls();
}
nAlert(getHwnd(), title, message);
LWJGLUtil.log(String.format("*** Alert *** %s\n%s\n", title, message));
// Pack both strings in the same buffer
final CharBuffer buffer = MemoryUtil.encodeUTF16(title, message);
final long address = MemoryUtil.getAddress0(buffer);
nAlert(getHwnd(), address, address + (title.length() + 1) * 2);
}
private static native void nAlert(long parent_hwnd, String title, String message);
private static native void nAlert(long parent_hwnd, long title, long message);
private static native void initCommonControls();
public boolean openURL(final String url) {

View file

@ -31,7 +31,7 @@
*/
package org.lwjgl.openal;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
@ -199,7 +199,8 @@ public final class ALC10 {
* @return opened device, or null
*/
public static ALCdevice alcOpenDevice(String devicename) {
long device_address = nalcOpenDevice(devicename);
ByteBuffer buffer = MemoryUtil.encodeASCII(devicename);
long device_address = nalcOpenDevice(MemoryUtil.getAddressSafe(buffer));
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
@ -209,7 +210,7 @@ public final class ALC10 {
}
return null;
}
static native long nalcOpenDevice(String devicename);
static native long nalcOpenDevice(long devicename);
/**
* The <code>alcCloseDevice</code> function allows the application (i.e. the client program) to
@ -395,11 +396,12 @@ public final class ALC10 {
* @return true if extension is available, false if not
*/
public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
boolean result = nalcIsExtensionPresent(getDevice(device), extName);
ByteBuffer buffer = MemoryUtil.encodeASCII(extName);
boolean result = nalcIsExtensionPresent(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
static native boolean nalcIsExtensionPresent(long device, String extName);
private static native boolean nalcIsExtensionPresent(long device, long extName);
/**
* Enumeration/token values are device independend, but tokens defined for
@ -412,11 +414,12 @@ public final class ALC10 {
* @return value of enumeration
*/
public static int alcGetEnumValue(ALCdevice device, String enumName) {
int result = nalcGetEnumValue(getDevice(device), enumName);
ByteBuffer buffer = MemoryUtil.encodeASCII(enumName);
int result = nalcGetEnumValue(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
static native int nalcGetEnumValue(long device, String enumName);
private static native int nalcGetEnumValue(long device, long enumName);
static long getDevice(ALCdevice device) {
if(device != null) {

View file

@ -92,7 +92,8 @@ public final class ALC11 {
* @return ALCdevice if it was possible to open a device
*/
public static ALCdevice alcCaptureOpenDevice(String devicename, int frequency, int format, int buffersize) {
long device_address = nalcCaptureOpenDevice(devicename, frequency, format, buffersize);
ByteBuffer buffer = MemoryUtil.encodeASCII(devicename);
long device_address = nalcCaptureOpenDevice(MemoryUtil.getAddress(buffer), frequency, format, buffersize);
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
@ -102,7 +103,7 @@ public final class ALC11 {
}
return null;
}
static native long nalcCaptureOpenDevice( String devicename, int frequency, int format, int buffersize);
private static native long nalcCaptureOpenDevice(long devicename, int frequency, int format, int buffersize);
/**
* The alcCaptureCloseDevice function allows the application to disconnect from a capture

View file

@ -33,6 +33,7 @@ package org.lwjgl.opencl;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.MemoryUtil;
import org.lwjgl.Sys;
import java.nio.ByteBuffer;
@ -143,7 +144,12 @@ public final class CL {
return 0;
}
static native long getFunctionAddress(String name);
/** Helper method to get a pointer to a named function in the OpenCL library. */
static long getFunctionAddress(String name) {
ByteBuffer buffer = MemoryUtil.encodeASCII(name);
return ngetFunctionAddress(MemoryUtil.getAddress(buffer));
}
private static native long ngetFunctionAddress(long name);
static native ByteBuffer getHostBuffer(final long address, final int size);

View file

@ -33,9 +33,11 @@ package org.lwjgl.opengl;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.MemoryUtil;
import org.lwjgl.Sys;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
@ -187,8 +189,12 @@ public final class GLContext {
return 0;
}
/** Helper method to get a pointer to a named function in the OpenGL library */
static native long getFunctionAddress(String name);
/** Helper method to get a pointer to a named function in the OpenGL library. */
static long getFunctionAddress(String name) {
ByteBuffer buffer = MemoryUtil.encodeASCII(name);
return ngetFunctionAddress(MemoryUtil.getAddress(buffer));
}
private static native long ngetFunctionAddress(long name);
/**
* Determine which extensions are available and returns the context profile mask. Helper method to ContextCapabilities.

View file

@ -38,15 +38,13 @@ package org.lwjgl.opengl;
* @author elias_naur
*/
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.*;
import java.awt.Canvas;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.BufferUtils;
import org.lwjgl.MemoryUtil;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengles.EGL;
@ -141,11 +139,11 @@ final class WindowsDisplay implements DisplayImplementation {
private static final int SWP_FRAMECHANGED = 0x0020;
private static final int GWL_STYLE = -16;
private static final int GWL_EXSTYLE = -20;
private static final int GWL_EXSTYLE = -20;
private static final int WS_THICKFRAME = 0x00040000;
private static WindowsDisplay current_display;
private static boolean cursor_clipped;
@ -217,9 +215,9 @@ final class WindowsDisplay implements DisplayImplementation {
}
peer_info.initDC(getHwnd(), getHdc());
showWindow(getHwnd(), SW_SHOWDEFAULT);
updateWidthAndHeight();
if ( parent == null ) {
if(Display.isResizable()) {
setResizable(true);
@ -233,7 +231,7 @@ final class WindowsDisplay implements DisplayImplementation {
throw e;
}
}
private void updateWidthAndHeight() {
getClientRect(hwnd, rect_buffer);
rect.copyFromBuffer(rect_buffer);
@ -440,9 +438,10 @@ final class WindowsDisplay implements DisplayImplementation {
private static native DisplayMode getCurrentDisplayMode() throws LWJGLException;
public void setTitle(String title) {
nSetTitle(hwnd, title);
CharBuffer buffer = MemoryUtil.encodeUTF16(title);
nSetTitle(hwnd, MemoryUtil.getAddress0(buffer));
}
private static native void nSetTitle(long hwnd, String title);
private static native void nSetTitle(long hwnd, long title);
public boolean isCloseRequested() {
boolean saved = close_requested;
@ -786,7 +785,7 @@ final class WindowsDisplay implements DisplayImplementation {
byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
boolean repeat = state == previous_state;
if (keyboard != null)
keyboard.handleChar((int)(wParam & 0xFF), millis, repeat);
keyboard.handleChar((int)(wParam & 0xFFFF), millis, repeat);
}
private void handleKeyButton(long wParam, long lParam, long millis) {
@ -991,12 +990,12 @@ final class WindowsDisplay implements DisplayImplementation {
public boolean isInsideWindow() {
return mouseInside;
}
public void setResizable(boolean resizable) {
if(this.resizable != resizable) {
long style = getWindowLongPtr(hwnd, GWL_STYLE);
long styleex = getWindowLongPtr(hwnd, GWL_EXSTYLE);
// update frame style
if(resizable) {
setWindowLongPtr(hwnd, GWL_STYLE, style |= WS_THICKFRAME);
@ -1010,16 +1009,16 @@ final class WindowsDisplay implements DisplayImplementation {
rect.copyFromBuffer(rect_buffer);
adjustWindowRectEx(rect_buffer, style, false, styleex);
rect.copyFromBuffer(rect_buffer);
// force a frame update and resize accordingly
setWindowPos(hwnd, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
updateWidthAndHeight();
resized = false;
}
this.resizable = resizable;
this.resizable = resizable;
}
private native boolean adjustWindowRectEx(IntBuffer rectBuffer, long style, boolean menu, long styleex);
public boolean wasResized() {

View file

@ -91,11 +91,13 @@ class SignatureTranslator implements TypeVisitor {
} else
type_name = t.getDeclaration().getQualifiedName();
signature.append("L");
signature.append(getNativeNameFromClassName(type_name));
signature.append(";");
if ( add_position_signature && Utils.isAddressableType(type) && !String.class.equals(type) )
signature.append("I");
if ( Utils.isAddressableType(type) && !String.class.equals(type) )
signature.append("J");
else {
signature.append("L");
signature.append(getNativeNameFromClassName(type_name));
signature.append(";");
}
}
public void visitDeclaredType(DeclaredType t) {