Implemented TerminalAccess.isTerminal() and Terminal.getTerminalSize() on windows.
This commit is contained in:
@@ -56,6 +56,7 @@ task nativeHeaders {
|
|||||||
args 'net.rubygrapefruit.platform.internal.PosixProcessFunctions'
|
args 'net.rubygrapefruit.platform.internal.PosixProcessFunctions'
|
||||||
args 'net.rubygrapefruit.platform.internal.PosixTerminalFunctions'
|
args 'net.rubygrapefruit.platform.internal.PosixTerminalFunctions'
|
||||||
args 'net.rubygrapefruit.platform.internal.TerminfoFunctions'
|
args 'net.rubygrapefruit.platform.internal.TerminfoFunctions'
|
||||||
|
args 'net.rubygrapefruit.platform.internal.WindowsConsoleFunctions'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
readme.md
Normal file → Executable file
7
readme.md
Normal file → Executable file
@@ -8,7 +8,11 @@ Provides Java bindings for various native APIs.
|
|||||||
* Switch between bold and normal mode on the terminal.
|
* Switch between bold and normal mode on the terminal.
|
||||||
* Change foreground color on the terminal.
|
* Change foreground color on the terminal.
|
||||||
|
|
||||||
Currently only ported to OS X (10.7.4) and Linux (Ubuntu 12.04).
|
Currently ported to OS X, Linux and Windows. Tested on:
|
||||||
|
|
||||||
|
* OS X 10.7.4
|
||||||
|
* Ubunutu 12.04 (amd64)
|
||||||
|
* Windows 7 (amd64)
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@@ -24,3 +28,4 @@ You need to install the `libncurses5-dev` package to pick up the ncurses header
|
|||||||
* Split into multiple projects.
|
* Split into multiple projects.
|
||||||
* Handle multiple architectures.
|
* Handle multiple architectures.
|
||||||
* IBM JVM.
|
* IBM JVM.
|
||||||
|
* Convert to c.
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* Generic functions
|
|
||||||
*/
|
|
||||||
#include "native.h"
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
|
||||||
Java_net_rubygrapefruit_platform_internal_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
21
src/main/cpp/generic.cpp
Executable file
21
src/main/cpp/generic.cpp
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Generic functions
|
||||||
|
*/
|
||||||
|
#include "native.h"
|
||||||
|
#include "generic.h"
|
||||||
|
|
||||||
|
void mark_failed_with_message(JNIEnv *env, const char* message, jobject result) {
|
||||||
|
mark_failed_with_code(env, message, 0, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, jobject result) {
|
||||||
|
jclass destClass = env->GetObjectClass(result);
|
||||||
|
jmethodID method = env->GetMethodID(destClass, "failed", "(Ljava/lang/String;I)V");
|
||||||
|
jstring message_str = env->NewStringUTF(message);
|
||||||
|
env->CallVoidMethod(result, method, message_str, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_net_rubygrapefruit_platform_internal_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
|
#include "generic.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -14,20 +15,7 @@
|
|||||||
* Marks the given result as failed, using the current value of errno
|
* Marks the given result as failed, using the current value of errno
|
||||||
*/
|
*/
|
||||||
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
||||||
jclass destClass = env->GetObjectClass(result);
|
mark_failed_with_code(env, message, errno, result);
|
||||||
jmethodID method = env->GetMethodID(destClass, "failed", "(Ljava/lang/String;I)V");
|
|
||||||
jstring message_str = env->NewStringUTF(message);
|
|
||||||
env->CallVoidMethod(result, method, message_str, errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Marks the given result as failed, using the given error message
|
|
||||||
*/
|
|
||||||
void mark_failed_with_message(JNIEnv *env, const char* message, jobject result) {
|
|
||||||
jclass destClass = env->GetObjectClass(result);
|
|
||||||
jmethodID method = env->GetMethodID(destClass, "failed", "(Ljava/lang/String;)V");
|
|
||||||
jstring message_str = env->NewStringUTF(message);
|
|
||||||
env->CallVoidMethod(result, method, message_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
#include "native.h"
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
|
||||||
Java_net_rubygrapefruit_platform_internal_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
|
|
||||||
return GetCurrentProcessId();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
73
src/main/cpp/win.cpp
Executable file
73
src/main/cpp/win.cpp
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include "native.h"
|
||||||
|
#include "generic.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marks the given result as failed, using the current value of GetLastError()
|
||||||
|
*/
|
||||||
|
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
||||||
|
mark_failed_with_code(env, message, GetLastError(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_net_rubygrapefruit_platform_internal_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
|
||||||
|
return GetCurrentProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Console functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
HANDLE getHandle(JNIEnv *env, int output, jobject result) {
|
||||||
|
HANDLE handle = output == 1 ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
mark_failed_with_errno(env, "could not get console handle", result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_net_rubygrapefruit_platform_internal_WindowsConsoleFunctions_isConsole(JNIEnv *env, jclass target, jint output, jobject result) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||||
|
HANDLE handle = getHandle(env, output, result);
|
||||||
|
if (handle == NULL) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
|
||||||
|
if (GetLastError() == ERROR_INVALID_HANDLE) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_net_rubygrapefruit_platform_internal_WindowsConsoleFunctions_getConsoleSize (JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO console_info;
|
||||||
|
HANDLE handle = getHandle(env, output, result);
|
||||||
|
if (handle == NULL) {
|
||||||
|
mark_failed_with_message(env, "not a terminal", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
|
||||||
|
mark_failed_with_errno(env, "could not get console buffer", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass dimensionClass = env->GetObjectClass(dimension);
|
||||||
|
jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
|
||||||
|
env->SetIntField(dimension, widthField, console_info.srWindow.Right - console_info.srWindow.Left + 1);
|
||||||
|
jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
|
||||||
|
env->SetIntField(dimension, heightField, console_info.srWindow.Bottom - console_info.srWindow.Top + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
24
src/main/headers/generic.h
Executable file
24
src/main/headers/generic.h
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __INCLUDE_GENERIC_H__
|
||||||
|
#define __INCLUDE_GENERIC_H__
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marks the given result as failed, using the given error message
|
||||||
|
*/
|
||||||
|
extern void mark_failed_with_message(JNIEnv *env, const char* message, jobject result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marks the given result as failed, using the given error message and error code
|
||||||
|
*/
|
||||||
|
extern void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, jobject result);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -191,11 +191,56 @@ public class Native {
|
|||||||
private static class WindowsTerminalAccess implements TerminalAccess {
|
private static class WindowsTerminalAccess implements TerminalAccess {
|
||||||
@Override
|
@Override
|
||||||
public boolean isTerminal(Output output) {
|
public boolean isTerminal(Output output) {
|
||||||
return false;
|
FunctionResult result = new FunctionResult();
|
||||||
|
boolean console = WindowsConsoleFunctions.isConsole(output.ordinal(), result);
|
||||||
|
if (result.isFailed()) {
|
||||||
|
throw new NativeException(String.format("Could not determine if %s is a console: %s", output,
|
||||||
|
result.getMessage()));
|
||||||
|
}
|
||||||
|
return console;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal getTerminal(Output output) {
|
public Terminal getTerminal(Output output) {
|
||||||
|
return new WindowsTerminal(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WindowsTerminal implements Terminal {
|
||||||
|
private final TerminalAccess.Output output;
|
||||||
|
|
||||||
|
public WindowsTerminal(TerminalAccess.Output output) {
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalSize getTerminalSize() {
|
||||||
|
FunctionResult result = new FunctionResult();
|
||||||
|
MutableTerminalSize size = new MutableTerminalSize();
|
||||||
|
WindowsConsoleFunctions.getConsoleSize(output.ordinal(), size, result);
|
||||||
|
if (result.isFailed()) {
|
||||||
|
throw new NativeException(String.format("Could not determine terminal size: %s", result.getMessage()));
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal bold() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal foreground(Color color) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal normal() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal reset() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.rubygrapefruit.platform.internal;
|
||||||
|
|
||||||
|
public class WindowsConsoleFunctions {
|
||||||
|
public static native boolean isConsole(int filedes, FunctionResult result);
|
||||||
|
|
||||||
|
public static native void getConsoleSize(int filedes, MutableTerminalSize size, FunctionResult result);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user