- JNI: open_file_in_termux via ACTION_SEND intent (text/plain + file:// uri), global context ref kept from registerFragment - impl_android.go: OpenFile(path) attaches current thread if needed - NewLogic takes openfunc; State.open + ui.OpenFile now func(string) - ChunkedBuffer.VisibleByteRange: word-wrap path using GlyphLayout.VisualLineStarts (+byteOffset, lineHeight, visual index param) - GlyphLayout gains LineHeight; drawWrappedText records VisualLineStarts - WordWrap default true; State.ByteOffset tracks first visible line - types: VisualLineIndex - scroll_fix_test.go (new) - debug prints left in place (WIP; cleanup in later phase)
122 lines
4.2 KiB
C
122 lines
4.2 KiB
C
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <jni.h>
|
|
#include <string.h>
|
|
#include "jni_android.h"
|
|
#include "_cgo_export.h"
|
|
|
|
// Global context
|
|
static jobject ctx = NULL;
|
|
|
|
void
|
|
registerFragment(JNIEnv *env, jobject view) {
|
|
jclass cls = (*env)->GetObjectClass(env, view);
|
|
jmethodID mid = (*env)->GetMethodID(env, cls, "getContext", "()Landroid/content/Context;");
|
|
jobject l_ctx = (*env)->CallObjectMethod(env, view, mid);
|
|
ctx = (*env)->NewGlobalRef(env, l_ctx);
|
|
cls = (*env)->GetObjectClass(env, ctx);
|
|
mid = (*env)->GetMethodID(env, cls, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
|
jobject loader = (*env)->CallObjectMethod(env, ctx, mid);
|
|
cls = (*env)->GetObjectClass(env, loader);
|
|
mid = (*env)->GetMethodID(env, cls, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
|
jstring str = (*env)->NewStringUTF(env, "st/wow/git/logbook/Permissions");
|
|
cls = (*env)->CallObjectMethod(env, loader, mid, str);
|
|
mid = (*env)->GetMethodID(env, cls, "<init>", "(Landroid/view/View;)V");
|
|
jobject inst = (*env)->NewObject(env, cls, mid, view);
|
|
}
|
|
|
|
void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) {
|
|
(*env)->CallVoidMethod(env, obj, methodID);
|
|
}
|
|
|
|
jint GetEnv(JavaVM *vm, JNIEnv **env, jint version) {
|
|
return (*vm)->GetEnv(vm, (void **)env, version);
|
|
}
|
|
|
|
jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) {
|
|
return (*vm)->AttachCurrentThread(vm, p_env, thr_args);
|
|
}
|
|
|
|
jint DetachCurrentThread(JavaVM *vm) {
|
|
return (*vm)->DetachCurrentThread(vm);
|
|
}
|
|
|
|
jobject
|
|
NewGlobalRef(JNIEnv *env, jobject o) {
|
|
return (*env)->NewGlobalRef(env, o);
|
|
}
|
|
|
|
|
|
|
|
// Open file in Termux's file editor via ACTION_SEND share intent.
|
|
// env: JNIEnv* from your JNI callback
|
|
// path: absolute filesystem path to the file (e.g. "/storage/emulated/0/foo.txt")
|
|
void open_file_in_termux(JNIEnv *env, const char *path) {
|
|
if (!ctx) return;
|
|
|
|
jclass intentClass = (*env)->FindClass(env, "android/content/Intent");
|
|
if (!intentClass) return;
|
|
|
|
// new Intent("android.intent.action.SEND")
|
|
jmethodID intentInit = (*env)->GetMethodID(env, intentClass, "<init>", "(Ljava/lang/String;)V");
|
|
if (!intentInit) return;
|
|
|
|
jstring actionSend = (*env)->NewStringUTF(env, "android.intent.action.SEND");
|
|
jobject intent = (*env)->NewObject(env, intentClass, intentInit, actionSend);
|
|
if (!intent) return;
|
|
|
|
// intent.setType("text/plain");
|
|
jmethodID setType = (*env)->GetMethodID(env, intentClass,
|
|
"setType", "(Ljava/lang/String;)Landroid/content/Intent;");
|
|
if (!setType) return;
|
|
|
|
jstring type = (*env)->NewStringUTF(env, "text/plain");
|
|
(*env)->CallObjectMethod(env, intent, setType, type);
|
|
|
|
// Uri uri = Uri.parse("file://" + path);
|
|
jclass uriClass = (*env)->FindClass(env, "android/net/Uri");
|
|
if (!uriClass) return;
|
|
|
|
jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass,
|
|
"parse", "(Ljava/lang/String;)Landroid/net/Uri;");
|
|
if (!uriParse) return;
|
|
|
|
// Build "file://" + path
|
|
size_t uriLen = strlen("file://") + strlen(path) + 1;
|
|
char *uriStr = (char *)malloc(uriLen);
|
|
if (!uriStr) return;
|
|
strcpy(uriStr, "file://");
|
|
strcat(uriStr, path);
|
|
|
|
jstring uriJstr = (*env)->NewStringUTF(env, uriStr);
|
|
jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, uriJstr);
|
|
free(uriStr);
|
|
|
|
if (!uri) return;
|
|
|
|
// intent.setData(uri);
|
|
jmethodID setData = (*env)->GetMethodID(env, intentClass,
|
|
"setData", "(Landroid/net/Uri;)Landroid/content/Intent;");
|
|
if (!setData) return;
|
|
|
|
(*env)->CallObjectMethod(env, intent, setData, uri);
|
|
|
|
// intent.putExtra("android.intent.extra.STREAM", uri.toString());
|
|
// Use putExtra(String, String)
|
|
jmethodID putExtra = (*env)->GetMethodID(env, intentClass,
|
|
"putExtra", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;");
|
|
if (!putExtra) return;
|
|
|
|
jstring extraKey = (*env)->NewStringUTF(env, "android.intent.extra.STREAM");
|
|
(*env)->CallObjectMethod(env, intent, putExtra, extraKey, uriJstr);
|
|
|
|
// ctx.startActivity(intent);
|
|
jclass contextClass = (*env)->GetObjectClass(env, ctx);
|
|
jmethodID startActivity = (*env)->GetMethodID(env, contextClass,
|
|
"startActivity", "(Landroid/content/Intent;)V");
|
|
if (!startActivity) return;
|
|
|
|
(*env)->CallVoidMethod(env, ctx, startActivity, intent);
|
|
}
|