├── fabric
├── wslgradlew
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── settings.gradle
├── .gitignore
├── preprocess.sh
├── gradle.properties
├── gradlew.bat
├── build.gradle
└── gradlew
├── forge
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── wslgradlew
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── gradlew
└── build.gradle
├── src
├── fabric
│ ├── resources
│ │ ├── assets
│ │ │ └── modid
│ │ │ │ └── icon.png
│ │ ├── cocoafab.mixins.json
│ │ ├── fabric.mod.json
│ │ └── cocoainput.accesswidener
│ └── java
│ │ └── jp
│ │ └── axer
│ │ └── cocoainput
│ │ ├── loader
│ │ ├── CocoaInputModMenu.java
│ │ └── FabricLoader.java
│ │ └── mixin
│ │ └── MinecraftMixin.java
├── main
│ ├── resources
│ │ ├── win
│ │ │ └── libwincocoainput.dll
│ │ └── cocoainput.mixins.json
│ └── java
│ │ └── jp
│ │ └── axer
│ │ └── cocoainput
│ │ ├── util
│ │ ├── WrapperUtil.java
│ │ ├── Tuple3.java
│ │ ├── ConfigPack.java
│ │ ├── Rect.java
│ │ ├── ModLogger.java
│ │ ├── FCConfig.java
│ │ ├── PreeditFormatter.java
│ │ └── TinyConfig.java
│ │ ├── plugin
│ │ ├── CocoaInputController.java
│ │ ├── IMEOperator.java
│ │ └── IMEReceiver.java
│ │ ├── arch
│ │ ├── dummy
│ │ │ ├── DummyIMEOperator.java
│ │ │ └── DummyController.java
│ │ ├── darwin
│ │ │ ├── Handle.java
│ │ │ ├── DarwinController.java
│ │ │ ├── CallbackFunction.java
│ │ │ └── DarwinIMEOperator.java
│ │ ├── x11
│ │ │ ├── Handle.java
│ │ │ ├── X11IMEOperator.java
│ │ │ ├── Logger.java
│ │ │ └── X11Controller.java
│ │ └── win
│ │ │ ├── WinIMEOperator.java
│ │ │ ├── Handle.java
│ │ │ ├── Logger.java
│ │ │ └── WinController.java
│ │ ├── mixin
│ │ ├── SharedConstantsMixin.java
│ │ ├── SignEditScreenMixin.java
│ │ ├── BookEditScreenMixin.java
│ │ └── EditBoxMixin.java
│ │ ├── wrapper
│ │ ├── EditBoxWrapper.java
│ │ ├── SignEditScreenWrapper.java
│ │ └── BookEditScreenWrapper.java
│ │ └── CocoaInput.java
└── forge
│ ├── resources
│ ├── pack.mcmeta
│ └── META-INF
│ │ ├── accesstransformer.cfg
│ │ └── mods.toml
│ └── java
│ └── jp
│ └── axer
│ └── cocoainput
│ └── loader
│ └── ForgeLoader.java
├── libcocoainput
├── darwin
│ ├── libcocoainput.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcuserdata
│ │ │ │ └── axer.xcuserdatad
│ │ │ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcuserdata
│ │ │ └── axer.xcuserdatad
│ │ │ │ └── xcschemes
│ │ │ │ └── xcschememanagement.plist
│ │ └── project.pbxproj
│ └── libcocoainput
│ │ ├── MinecraftView.m
│ │ ├── Logger.h
│ │ ├── MinecraftView.h
│ │ ├── Makefile
│ │ ├── Logger.m
│ │ ├── cocoainput.h
│ │ ├── DataManager.h
│ │ ├── cocoainput.m
│ │ └── DataManager.m
├── win
│ ├── .project
│ ├── logger.h
│ ├── libwincocoainput.h
│ ├── Makefile
│ ├── logger.c
│ └── libwincocoainput.c
└── x11
│ ├── logger.h
│ ├── Makefile
│ ├── logger.c
│ ├── libx11cocoainput.h
│ └── libx11cocoainput.c
├── .gitignore
├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── README.MD
└── LICENSE
/fabric/wslgradlew:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cmd.exe /c 'SET JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.1.12-hotspot&gradlew '"$@"
3 |
--------------------------------------------------------------------------------
/forge/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Axeryok/CocoaInput/HEAD/forge/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/forge/wslgradlew:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cmd.exe /c 'SET JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.1.12-hotspot&gradlew '"$@"
3 |
--------------------------------------------------------------------------------
/fabric/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Axeryok/CocoaInput/HEAD/fabric/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/fabric/resources/assets/modid/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Axeryok/CocoaInput/HEAD/src/fabric/resources/assets/modid/icon.png
--------------------------------------------------------------------------------
/src/main/resources/win/libwincocoainput.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Axeryok/CocoaInput/HEAD/src/main/resources/win/libwincocoainput.dll
--------------------------------------------------------------------------------
/src/fabric/resources/cocoafab.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "package":"jp.axer.cocoainput.mixin",
3 | "mixins":[
4 | "MinecraftMixin" ],
5 | "required":true
6 | }
--------------------------------------------------------------------------------
/fabric/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven {
4 | name = 'Fabric'
5 | url = 'https://maven.fabricmc.net/'
6 | }
7 | gradlePluginPortal()
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/fabric/.gitignore:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | .DS_Store
4 | *.dylib
5 | *.so
6 | *.dll
7 | *.o
8 |
9 |
10 | !.gitignore
11 | !gradle
12 | !gradle.properties
13 | !gradlew
14 | !gradlew.bat
15 | !wslgradlew
16 | !preprocess.sh
17 | !build.gradle
18 | !settings.gradle
19 |
--------------------------------------------------------------------------------
/forge/.gitignore:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | .DS_Store
4 | *.dylib
5 | *.so
6 | *.dll
7 | *.o
8 |
9 |
10 | !.gitignore
11 | !gradle
12 | !gradle.properties
13 | !gradlew
14 | !gradlew.bat
15 | !wslgradlew
16 | !preprocess.sh
17 | !build.gradle
18 | !settings.gradle
19 |
--------------------------------------------------------------------------------
/forge/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/src/forge/resources/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack": {
3 | "description": "examplemod resources",
4 | "pack_format": 4,
5 | "_comment": "A pack_format of 4 requires json lang files. Note: we require v4 pack meta for all mods."
6 | }
7 | }
--------------------------------------------------------------------------------
/src/main/resources/cocoainput.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "package":"jp.axer.cocoainput.mixin",
3 | "mixins":[
4 | "SharedConstantsMixin",
5 | "EditBoxMixin",
6 | "SignEditScreenMixin",
7 | "BookEditScreenMixin"
8 | ],
9 | "required":true
10 | }
--------------------------------------------------------------------------------
/fabric/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/forge/gradle.properties:
--------------------------------------------------------------------------------
1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties.
2 | # This is required to provide enough memory for the Minecraft decompilation process.
3 | org.gradle.jvmargs=-Xmx3G
4 | org.gradle.daemon=false
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput.xcodeproj/project.xcworkspace/xcuserdata/axer.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Axeryok/CocoaInput/HEAD/libcocoainput/darwin/libcocoainput.xcodeproj/project.xcworkspace/xcuserdata/axer.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/libcocoainput/win/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | libwincocoainput
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/libcocoainput/win/logger.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | typedef void (*LogFunction)(const char *);
4 |
5 |
6 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug);
7 |
8 | void CILog(const char *msg,...);
9 | void CIError(const char *msg,...);
10 | void CIDebug(const char *msg,...);
11 |
--------------------------------------------------------------------------------
/libcocoainput/x11/logger.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | typedef void (*LogFunction)(const char *);
4 |
5 |
6 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug);
7 |
8 | void CILog(const char *msg,...);
9 | void CIError(const char *msg,...);
10 | void CIDebug(const char *msg,...);
11 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/WrapperUtil.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | import net.minecraft.client.gui.Font;
4 | import net.minecraft.client.gui.screens.Screen;
5 |
6 |
7 | public class WrapperUtil {
8 | public static Font makeFont(Screen owner) throws Exception {
9 | return owner.font;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/fabric/preprocess.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rm -r src/autogen
3 | mkdir -p src/autogen/
4 | cp -r ../src/main/* src/autogen/
5 | mv src/autogen/resources/cocoainput.mixins.json src/autogen/java
6 | cd src/autogen/java
7 | find . -type f -print0 | xargs -0 sed -i -e 's/"refmap":"cocoainput.refmap.json",//g'
8 | mv cocoainput.mixins.json ../resources
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/plugin/CocoaInputController.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.plugin;
2 |
3 | import net.minecraft.client.gui.screens.Screen;
4 |
5 | public interface CocoaInputController {
6 | IMEOperator generateIMEOperator(IMEReceiver ime); //GuiTextFieldとかが作成された時に割り当てるIMEOperator生成処理を委託
7 | void screenOpenNotify(Screen sc);
8 | }
9 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | .DS_Store
4 | *.dylib
5 | *.so
6 | *.dll
7 | *.o
8 |
9 |
10 | !.gitignore
11 | !src
12 | !libcocoainput
13 | !README.MD
14 | !build_lib_for_mac.sh
15 | !build_lib_for_win.sh
16 | !build_lib_for_x11.sh
17 | !build_lib_all.sh
18 | !build_cocoainput_all_platform.sh
19 | !TODO.txt
20 | !LICENSE
21 |
22 | libcocoainput/build
23 |
24 | !fabric
25 | !forge
26 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/plugin/IMEOperator.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.plugin;
2 |
3 | public interface IMEOperator {
4 | void setFocused(boolean inFocused);//保持するIMEのフォーカスが変化した時に呼び出される
5 | void discardMarkedText();//実装してないので呼び出されない(いつか実装する)
6 |
7 | //TODO removeInstanceを実装する(現時点では呼ばれない)
8 | void removeInstance();//看板や本の編集が終わった時に呼び出される テキストフィールドは廃棄位置が曖昧なため呼び出されない
9 |
10 | }
--------------------------------------------------------------------------------
/libcocoainput/win/libwincocoainput.h:
--------------------------------------------------------------------------------
1 | //#include
2 | #include
3 | #include
4 |
5 | #include "logger.h"
6 |
7 |
8 |
9 | void initialize(
10 | long hwnd,
11 | int*(*c_draw)(wchar_t*,int,int),
12 | void(*c_done)(wchar_t*),
13 | int (*c_rect)(float*),
14 | LogFunction log,
15 | LogFunction error,
16 | LogFunction debug
17 | );
18 |
19 |
20 |
21 |
22 | void set_focus(int flag);
23 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/MinecraftView.m:
--------------------------------------------------------------------------------
1 | //
2 | // MinecraftView.m
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import "MinecraftView.h"
10 | #import "DataManager.h"
11 | #import "Logger.h"
12 |
13 | @implementation MinecraftView
14 |
15 | - (id)init {
16 | self = [super init];
17 | return self;
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/Tuple3.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | public class Tuple3 {
4 | A va;
5 | B vb;
6 | C vc;
7 |
8 | public Tuple3(A a, B b, C c) {
9 | va=a;
10 | vb=b;
11 | vc=c;
12 | }
13 | public A _1(){
14 | return va;
15 | }
16 |
17 | public B _2(){
18 | return vb;
19 | }
20 |
21 | public C _3(){
22 | return vc;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/Logger.h:
--------------------------------------------------------------------------------
1 | //
2 | // Logger.h
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void (*LogFunction)(const char*);
12 |
13 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug);
14 |
15 | void CILog(NSString* msg);
16 | void CIError(NSString* msg);
17 | void CIDebug(NSString* msg);
18 |
--------------------------------------------------------------------------------
/fabric/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx1G
3 |
4 | # Fabric Properties
5 | # check these on https://fabricmc.net/use
6 | minecraft_version=1.18
7 | yarn_mappings=1.18+build.1
8 | loader_version=0.12.8
9 |
10 | # Mod Properties
11 | mod_version = 4.0.4
12 | maven_group = jp.axer.cocoainput
13 | archives_base_name = CocoaInput-1.18-fabric
14 |
15 | # Dependencies
16 | fabric_version=0.44.0+1.18
17 | modmenu_version=3.0.0
18 |
--------------------------------------------------------------------------------
/src/fabric/java/jp/axer/cocoainput/loader/CocoaInputModMenu.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.loader;
2 |
3 |
4 | import com.terraformersmc.modmenu.api.ModMenuApi;
5 | import com.terraformersmc.modmenu.api.ConfigScreenFactory;
6 | import jp.axer.cocoainput.util.FCConfig;
7 |
8 | public class CocoaInputModMenu implements ModMenuApi {
9 |
10 | @Override
11 | public ConfigScreenFactory> getModConfigScreenFactory() {
12 | return parent -> (new FCConfig().getScreen(parent));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput.xcodeproj/xcuserdata/axer.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | libcocoainput.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/ConfigPack.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | public interface ConfigPack {
4 |
5 | public static ConfigPack defaultConfig = new ConfigPack() {
6 | @Override
7 | public boolean isAdvancedPreeditDraw() {
8 | return true;
9 | }
10 | @Override
11 | public boolean isNativeCharTyped() {
12 | return true;
13 | }
14 | };
15 |
16 | public boolean isAdvancedPreeditDraw();
17 | public boolean isNativeCharTyped();
18 | }
19 |
--------------------------------------------------------------------------------
/libcocoainput/x11/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | CFLAGS = -Wall -fPIC
3 | FFLAGS = -lX11
4 | OBJS = libx11cocoainput.o logger.o
5 | LIBS =
6 | TARGET = libx11cocoainput.so
7 | DISTDIR = ../../src/main/resources/x11/
8 | RM = rm
9 | CP = cp
10 |
11 | all: $(TARGET)
12 |
13 | install: $(TARGET)
14 | $(CP) -f $(TARGET) $(DISTDIR)
15 |
16 | $(TARGET): $(OBJS)
17 | $(CC) $(OBJS) $(CFLAGS) $(FFLAGS) $(LIBS) -shared -o $@
18 |
19 | .c.o:
20 | $(CC) $(CFLAGS) $(LIBS) -c $<
21 |
22 | clean:
23 | $(RM) -f $(TARGET) $(OBJS)
24 |
--------------------------------------------------------------------------------
/libcocoainput/win/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc.exe
2 | CFLAGS = -Wall -fPIC
3 | FFLAGS =
4 | OBJS = libwincocoainput.o logger.o
5 | LIBS =
6 | TARGET = libwincocoainput.dll
7 | DISTDIR = ../../src/main/resources/win/
8 | RM = rm
9 | CP = cp
10 |
11 | all: $(TARGET)
12 |
13 | install: $(TARGET)
14 | $(CP) -f $(TARGET) $(DISTDIR)
15 |
16 | $(TARGET): $(OBJS)
17 | $(CC) $(CFLAGS) $(FFLAGS) $(LIBS) -shared -o $@ $(OBJS) -limm32
18 |
19 | .c.o:
20 | $(CC) $(CFLAGS) $(LIBS) -c $<
21 |
22 | clean:
23 | $(RM) -f $(TARGET) $(OBJS)
24 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/MinecraftView.h:
--------------------------------------------------------------------------------
1 | //
2 | // MinecraftView.h
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface MinecraftView : NSObject
13 | @property void (*insertText)(const char*, const int, const int);
14 | @property void (*setMarkedText)(const char*, const int, const int, const int, const int);
15 | @property float* (*firstRectForCharacterRange)(void);
16 | @end
17 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/dummy/DummyIMEOperator.java:
--------------------------------------------------------------------------------
1 |
2 | package jp.axer.cocoainput.arch.dummy;
3 |
4 |
5 | import jp.axer.cocoainput.plugin.IMEOperator;
6 |
7 | public class DummyIMEOperator implements IMEOperator {
8 |
9 | @Override
10 | public void setFocused(boolean inFocused) {
11 | // TODO 自動生成されたメソッド・スタブ
12 |
13 | }
14 |
15 | @Override
16 | public void discardMarkedText() {
17 | // TODO 自動生成されたメソッド・スタブ
18 |
19 | }
20 |
21 | @Override
22 | public void removeInstance() {
23 | // TODO 自動生成されたメソッド・スタブ
24 |
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | CFLAGS = -Wall -fobjc-arc -mmacosx-version-min=10.10
3 | FFLAGS = -framework Foundation -framework Cocoa
4 | OBJS = cocoainput.o Logger.o DataManager.o MinecraftView.o
5 | LIBS =
6 | TARGET = libcocoainput.dylib
7 | DISTDIR = ../../../src/main/resources/darwin/
8 | RM = rm
9 | CP = cp
10 |
11 | all: $(TARGET)
12 |
13 | install: $(TARGET)
14 | $(CP) -f $(TARGET) $(DISTDIR)
15 |
16 | $(TARGET): $(OBJS)
17 | $(CC) $(CFLAGS) $(FFLAGS) $(LIBS) -shared -o $@ $(OBJS)
18 |
19 | .c.o:
20 | $(CC) $(CFLAGS) $(LIBS) -c $<
21 |
22 | clean:
23 | $(RM) -f $(TARGET) $(OBJS)
24 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/mixin/SharedConstantsMixin.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Mixin;
4 | import org.spongepowered.asm.mixin.Overwrite;
5 |
6 | import net.minecraft.SharedConstants;
7 |
8 |
9 | @Mixin(SharedConstants.class)
10 | public class SharedConstantsMixin {
11 | //@ModifyConstant(method="isAllowedChatCharacter",constant=@Constant(intValue=167))
12 | //@Inject(at=@At("HEAD"),method="isAllowedChatCharacter")
13 | @Overwrite
14 | public static boolean isAllowedChatCharacter(char p) {
15 | return p>=' '&&p!=127;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ** Describe the bug **
11 |
12 | ** Describe the environment **
13 | - OS: [e.g. Ubuntu 18.04lts]
14 | - Arch: [e.g. x86_64]
15 | - IME: [e.g. fcitx/mozc]
16 | - Minecraft [e.g. 1.12]
17 | - ModVersion [e.g. 4.0.0]
18 | - ModSetting [ look curseforge]
19 |
20 |
21 | **To Reproduce**
22 | Steps to reproduce the behavior:
23 | 1. Go to '...'
24 | 2. Click on '....'
25 | 3. Scroll down to '....'
26 | 4. See error
27 |
28 | **Logs(URL)**
29 | No logs no solutions
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/Rect.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | public class Rect {
4 | private float x;
5 | private float y;
6 | private float height;
7 | private float width;
8 |
9 | public Rect(float x, float y, float width, float height) {
10 | this.x = x;
11 | this.y = y;
12 | this.height = height;
13 | this.width = width;
14 | }
15 |
16 | public float getX() {
17 | return this.x;
18 | }
19 |
20 | public float getY() {
21 | return this.y;
22 | }
23 |
24 | public float getWidth() {
25 | return this.width;
26 | }
27 |
28 | public float getHeight() {
29 | return this.height;
30 | }
31 | }
--------------------------------------------------------------------------------
/src/fabric/java/jp/axer/cocoainput/mixin/MinecraftMixin.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Mixin;
4 | import org.spongepowered.asm.mixin.injection.At;
5 | import org.spongepowered.asm.mixin.injection.Inject;
6 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
7 |
8 | import jp.axer.cocoainput.loader.FabricLoader;
9 | import net.minecraft.client.Minecraft;
10 | import net.minecraft.client.gui.screens.Screen;
11 |
12 | @Mixin(Minecraft.class)
13 | public class MinecraftMixin {
14 | @Inject(method="setScreen",at=@At("HEAD"))
15 | private void setScreen(Screen screen,CallbackInfo ci) {
16 | FabricLoader.instance.onChangeScreen(screen);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/ModLogger.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | import org.apache.logging.log4j.Level;
4 | import org.apache.logging.log4j.LogManager;
5 |
6 | public class ModLogger {
7 | public static boolean debugMode=true;
8 |
9 | public static void log(String msg,Object...data){
10 | LogManager.getLogger("CocoaInput:Java").log( Level.INFO,msg, data);
11 | }
12 |
13 | public static void error(String msg,Object...data){
14 | LogManager.getLogger("CocoaInput:Java").error(msg, data);
15 | }
16 |
17 | public static void debug(String msg,Object...data){
18 | if(debugMode){
19 | LogManager.getLogger("CocoaInput:Java").debug(msg, data);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/dummy/DummyController.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.dummy;
2 |
3 | import jp.axer.cocoainput.plugin.CocoaInputController;
4 | import jp.axer.cocoainput.plugin.IMEOperator;
5 | import jp.axer.cocoainput.plugin.IMEReceiver;
6 | import jp.axer.cocoainput.util.ModLogger;
7 | import net.minecraft.client.gui.screens.Screen;
8 |
9 | public class DummyController implements CocoaInputController{
10 | public DummyController() {
11 | ModLogger.log("This is a dummy controller.");
12 | }
13 |
14 | @Override
15 | public IMEOperator generateIMEOperator(IMEReceiver ime) {
16 | return new DummyIMEOperator();
17 | }
18 |
19 | @Override
20 | public void screenOpenNotify(Screen sc) {
21 | // TODO 自動生成されたメソッド・スタブ
22 |
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/FCConfig.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | import jp.axer.cocoainput.util.ConfigPack;
4 |
5 | public class FCConfig extends TinyConfig implements ConfigPack{
6 |
7 | @Entry(comment="AdvancedPreeditDraw - Is preedit marking - Default:true")
8 | public static boolean advancedPreeditDraw=true;
9 | @Entry(comment="NativeCharTyped - Is text inserted with native way - Default:true")
10 | public static boolean nativeCharTyped=true;
11 |
12 |
13 |
14 | @Override
15 | public boolean isAdvancedPreeditDraw() {
16 | // TODO 自動生成されたメソッド・スタブ
17 | return advancedPreeditDraw;
18 | }
19 | @Override
20 | public boolean isNativeCharTyped() {
21 | // TODO 自動生成されたメソッド・スタブ
22 | return nativeCharTyped;
23 | }
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/darwin/Handle.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.darwin;
2 |
3 | import jp.axer.cocoainput.arch.darwin.CallbackFunction.*;
4 | import com.sun.jna.Callback;
5 | import com.sun.jna.Library;
6 | import com.sun.jna.Native;
7 |
8 | public interface Handle extends Library{
9 | Handle INSTANCE=(Handle)Native.loadLibrary("cocoainput", Handle.class);
10 |
11 |
12 | void initialize(Callback log,Callback error,Callback debug);
13 | void refreshInstance();
14 | void addInstance(String uuid, Func_insertText insertText_p, Func_setMarkedText setMarkedText_p, Func_firstRectForCharacterRange firstRectForCharacterRange_p);
15 | void removeInstance(String uuid);
16 | void discardMarkedText(String uuid);
17 | void setIfReceiveEvent(String uuid,int yn);
18 | float invertYCoordinate(float y);
19 | }
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/Logger.m:
--------------------------------------------------------------------------------
1 | //
2 | // Logger.m
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import "Logger.h"
10 |
11 | struct {
12 | LogFunction log;
13 | LogFunction error;
14 | LogFunction debug;
15 | } LogPointer;
16 |
17 | void CILog(NSString* msg) {
18 | LogPointer.log([msg cStringUsingEncoding:NSUTF8StringEncoding]);
19 | }
20 | void CIError(NSString* msg) {
21 | LogPointer.error([msg cStringUsingEncoding:NSUTF8StringEncoding]);
22 | }
23 | void CIDebug(NSString* msg) {
24 | LogPointer.debug([msg cStringUsingEncoding:NSUTF8StringEncoding]);
25 | }
26 |
27 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug) {
28 | LogPointer.log = log;
29 | LogPointer.error = error;
30 | LogPointer.debug = debug;
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/PreeditFormatter.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 |
3 | public class PreeditFormatter {
4 | public static final char SECTION = 167; // avoid shift-jis bug...
5 |
6 | public static Tuple3 formatMarkedText(String aString, int position1, int length1) {//ユーティリティ
7 | StringBuilder builder = new StringBuilder(aString);
8 | boolean hasCaret = length1 == 0;
9 | if (!hasCaret) {//主文節がある
10 | builder.insert(position1 + length1, SECTION+"r"+SECTION+"n");//主文節の終わりで修飾をリセットして下線修飾をセット
11 | builder.insert(position1, SECTION+"l");//主文節の始まりで太字修飾を追加
12 | } else {//主文説がない(キャレットが存在するのでそれを意識する)
13 | builder.insert(position1, SECTION+"r"+SECTION+"n");
14 | }
15 | builder.insert(0, SECTION+"r"+SECTION+"n");//最初に下線修飾をセット
16 | builder.append(SECTION+"r");//最後に修飾をリセット
17 | return new Tuple3(new String(builder), position1, hasCaret);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/x11/Handle.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.x11;
2 |
3 | import com.sun.jna.Callback;
4 | import com.sun.jna.Library;
5 | import com.sun.jna.Native;
6 | import com.sun.jna.Pointer;
7 | import com.sun.jna.WString;
8 |
9 | public interface Handle extends Library{
10 | Handle INSTANCE = (Handle)Native.loadLibrary("x11cocoainput", Handle.class);
11 |
12 | void set_focus(int flag);
13 | void initialize(
14 | long window,
15 | long xw,
16 | DrawCallback paramDrawCallback,
17 | DoneCallback paramDoneCallback,
18 | Callback log,
19 | Callback error,
20 | Callback debug
21 | );
22 |
23 | public static interface DrawCallback extends Callback {
24 | Pointer invoke(int param1Int1, int param1Int2, int param1Int3, short param1Short, boolean param1Boolean, String param1String, WString param1WString, int param1Int4, int param1Int5, int param1Int6);
25 | }
26 | public static interface DoneCallback extends Callback {
27 | void invoke();
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/fabric/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "cocoainput",
4 | "version": "${version}",
5 |
6 | "name": "CocoaInput",
7 | "description": "This is an example description! Tell everyone what your mod is about!",
8 | "authors": [
9 | "Axeryok"
10 | ],
11 | "contact": {
12 | "homepage": "https://fabricmc.net/",
13 | "sources": "https://github.com/FabricMC/fabric-example-mod"
14 | },
15 |
16 | "license": "MMPLJ",
17 | "icon": "assets/modid/icon.png",
18 |
19 | "environment": "*",
20 | "entrypoints": {
21 | "client": [
22 | "jp.axer.cocoainput.loader.FabricLoader"
23 | ],
24 | "modmenu":[
25 | "jp.axer.cocoainput.loader.CocoaInputModMenu"
26 | ]
27 | },
28 |
29 | "depends": {
30 | "fabricloader": ">=0.11.3",
31 | "minecraft": ">=1.18",
32 | "java": ">=16"
33 | },
34 | "suggests": {
35 | "another-mod": "*"
36 | },
37 | "accessWidener":"cocoainput.accesswidener",
38 | "mixins": [
39 | "cocoainput.mixins.json",
40 | "cocoafab.mixins.json"
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/cocoainput.h:
--------------------------------------------------------------------------------
1 | //
2 | // cocoainput.h
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "Logger.h"
12 |
13 |
14 | void initialize(LogFunction log,LogFunction error,LogFunction debug);
15 | void replaceInstanceMethod(Class cls, SEL sel, SEL renamedSel, Class dataCls);
16 |
17 | void addInstance(const char* uuid,
18 | void (*insertText_p)(const char*, const int, const int),
19 | void (*setMarkedText_p)(const char*,
20 | const int,
21 | const int,
22 | const int,
23 | const int),
24 | float* (*firstRectForCharacterRange)(void));
25 | void removeInstance(const char* uuid);
26 | void refreshInstance(void);
27 |
28 | void discardMarkedText(const char* uuid);
29 | void setIfReceiveEvent(const char* uuid, int yn);
30 |
--------------------------------------------------------------------------------
/libcocoainput/win/logger.c:
--------------------------------------------------------------------------------
1 | #define _GNU_SOURCE
2 |
3 | #include "logger.h"
4 | #include
5 | #include
6 |
7 | struct {
8 | LogFunction log;
9 | LogFunction error;
10 | LogFunction debug;
11 | } LogPointer;
12 |
13 | void CILog(const char* format,...) {
14 | char *msg;
15 | va_list args;
16 | va_start(args,format);
17 | vasprintf(&msg,format,args);
18 | LogPointer.log(msg);
19 | free(msg);
20 | va_end(args);
21 | }
22 |
23 |
24 | void CIError(const char* format,...) {
25 | char *msg;
26 | va_list args;
27 | va_start(args,format);
28 | vasprintf(&msg,format,args);
29 | LogPointer.error(msg);
30 | free(msg);
31 | va_end(args);
32 | }
33 |
34 |
35 | void CIDebug(const char* format,...) {
36 | char *msg;
37 | va_list args;
38 | va_start(args,format);
39 | vasprintf(&msg,format,args);
40 | LogPointer.debug(msg);
41 | free(msg);
42 | va_end(args);
43 | }
44 |
45 |
46 |
47 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug) {
48 | LogPointer.log = log;
49 | LogPointer.error = error;
50 | LogPointer.debug = debug;
51 | }
52 |
--------------------------------------------------------------------------------
/libcocoainput/x11/logger.c:
--------------------------------------------------------------------------------
1 | #define _GNU_SOURCE
2 |
3 | #include "logger.h"
4 | #include
5 | #include
6 |
7 | struct {
8 | LogFunction log;
9 | LogFunction error;
10 | LogFunction debug;
11 | } LogPointer;
12 |
13 | void CILog(const char* format,...) {
14 | char *msg;
15 | va_list args;
16 | va_start(args,format);
17 | vasprintf(&msg,format,args);
18 | LogPointer.log(msg);
19 | free(msg);
20 | va_end(args);
21 | }
22 |
23 |
24 | void CIError(const char* format,...) {
25 | char *msg;
26 | va_list args;
27 | va_start(args,format);
28 | vasprintf(&msg,format,args);
29 | LogPointer.error(msg);
30 | free(msg);
31 | va_end(args);
32 | }
33 |
34 |
35 | void CIDebug(const char* format,...) {
36 | char *msg;
37 | va_list args;
38 | va_start(args,format);
39 | vasprintf(&msg,format,args);
40 | LogPointer.debug(msg);
41 | free(msg);
42 | va_end(args);
43 | }
44 |
45 |
46 |
47 | void initLogPointer(LogFunction log,LogFunction error,LogFunction debug) {
48 | LogPointer.log = log;
49 | LogPointer.error = error;
50 | LogPointer.debug = debug;
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/mixin/SignEditScreenMixin.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.mixin;
2 |
3 | import org.objectweb.asm.Opcodes;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.injection.At;
6 | import org.spongepowered.asm.mixin.injection.Inject;
7 | import org.spongepowered.asm.mixin.injection.Redirect;
8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9 |
10 | import jp.axer.cocoainput.wrapper.SignEditScreenWrapper;
11 | import net.minecraft.client.gui.screens.inventory.SignEditScreen;
12 |
13 | @Mixin(SignEditScreen.class)
14 | public class SignEditScreenMixin {
15 | SignEditScreenWrapper wrapper;
16 |
17 | @Inject(method="init",at=@At("RETURN"))
18 | private void init(CallbackInfo ci) {
19 | wrapper = new SignEditScreenWrapper((SignEditScreen)(Object)this);
20 | }
21 |
22 | @Redirect(method="tick",at = @At(value="FIELD", target="Lnet/minecraft/client/gui/screens/inventory/SignEditScreen;frame:I",opcode=Opcodes.PUTFIELD))
23 | private void injectCurosr(SignEditScreen esc,int n) {
24 | esc.frame=wrapper.renewCursorCounter();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/mixin/BookEditScreenMixin.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.mixin;
2 |
3 | import org.objectweb.asm.Opcodes;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.injection.At;
6 | import org.spongepowered.asm.mixin.injection.Inject;
7 | import org.spongepowered.asm.mixin.injection.Redirect;
8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9 |
10 | import jp.axer.cocoainput.wrapper.BookEditScreenWrapper;
11 | import net.minecraft.client.gui.screens.inventory.BookEditScreen;
12 |
13 | @Mixin(BookEditScreen.class)
14 | public class BookEditScreenMixin {
15 | BookEditScreenWrapper wrapper;
16 |
17 | @Inject(method="init*",at=@At("RETURN"))
18 | private void init(CallbackInfo ci) {
19 | wrapper = new BookEditScreenWrapper((BookEditScreen)(Object)this);
20 | }
21 |
22 | @Redirect(method="tick",at = @At(value="FIELD", target="Lnet/minecraft/client/gui/screens/inventory/BookEditScreen;frameTick:I",opcode=Opcodes.PUTFIELD))
23 | private void injectCurosr(BookEditScreen esc,int n) {
24 | esc.frameTick=wrapper.renewCursorCounter();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/win/WinIMEOperator.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.win;
2 |
3 | import jp.axer.cocoainput.plugin.IMEOperator;
4 | import jp.axer.cocoainput.plugin.IMEReceiver;
5 |
6 | public class WinIMEOperator implements IMEOperator {
7 | public IMEReceiver owner;
8 | private boolean focus=false;
9 | public WinIMEOperator(IMEReceiver op) {
10 | this.owner=op;
11 | }
12 |
13 | @Override
14 | public void discardMarkedText() {
15 | // TODO Auto-generated method stub
16 |
17 | }
18 |
19 | @Override
20 | public void removeInstance() {
21 | // TODO Auto-generated method stub
22 |
23 | }
24 |
25 | @Override
26 | public void setFocused(boolean arg0) {
27 | // TODO Auto-generated method stub
28 | if(arg0==focus) {
29 | return ;
30 | }
31 | focus=arg0;
32 | Logger.log("setFocusedCalled "+ arg0);
33 | if(arg0) {
34 | WinController.focusedOperator=this;
35 | Handle.INSTANCE.set_focus(1);
36 | }
37 | else {
38 | if(WinController.focusedOperator==this) {
39 | owner.insertText("", 0, 0);
40 | WinController.focusedOperator=null;
41 | Handle.INSTANCE.set_focus(0);
42 | }
43 | }
44 |
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/mixin/EditBoxMixin.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Mixin;
4 | import org.spongepowered.asm.mixin.injection.At;
5 | import org.spongepowered.asm.mixin.injection.Inject;
6 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
7 |
8 | import jp.axer.cocoainput.wrapper.EditBoxWrapper;
9 | import net.minecraft.client.gui.components.EditBox;
10 |
11 | @Mixin(EditBox.class)
12 | public class EditBoxMixin {
13 | EditBoxWrapper wrapper;
14 |
15 | @Inject(method="*",at=@At("RETURN"))
16 | private void init(CallbackInfo ci) {
17 | wrapper = new EditBoxWrapper((EditBox)(Object)this);
18 | }
19 |
20 | @Inject(method="setFocus",at=@At("HEAD"))
21 | private void setFocus(boolean b,CallbackInfo ci) {
22 | wrapper.setFocused(b);
23 | }
24 | @Inject(method="setCanLoseFocus",at=@At("HEAD"))
25 | private void setCanLoseFocus(boolean b,CallbackInfo ci) {
26 | wrapper.setCanLoseFocus(b);
27 | }
28 | @Inject(method="tick",at=@At("HEAD"),cancellable=true)
29 | private void tick(CallbackInfo ci) {
30 | wrapper.updateCursorCounter();
31 | ci.cancel();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/x11/X11IMEOperator.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.x11;
2 |
3 | import jp.axer.cocoainput.plugin.IMEOperator;
4 | import jp.axer.cocoainput.plugin.IMEReceiver;
5 |
6 | public class X11IMEOperator implements IMEOperator {
7 | public IMEReceiver owner;
8 | private boolean focus=false;
9 | public X11IMEOperator(IMEReceiver op) {
10 | this.owner=op;
11 | }
12 |
13 | @Override
14 | public void discardMarkedText() {
15 | // TODO Auto-generated method stub
16 |
17 | }
18 |
19 | @Override
20 | public void removeInstance() {
21 | // TODO Auto-generated method stub
22 |
23 | }
24 |
25 | @Override
26 | public void setFocused(boolean arg0) {
27 | // TODO Auto-generated method stub
28 | if(arg0==focus) {
29 | return ;
30 | }
31 | focus=arg0;
32 | Logger.log("setFocusedCalled "+ arg0);
33 | if(arg0) {
34 | X11Controller.focusedOperator=this;
35 | Handle.INSTANCE.set_focus(1);
36 | }
37 | else {
38 | if(X11Controller.focusedOperator==this) {
39 | owner.insertText("", 0, 0);
40 | X11Controller.focusedOperator=null;
41 | Handle.INSTANCE.set_focus(0);
42 | X11Controller.setupKeyboardEvent();
43 | }
44 | }
45 |
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/win/Handle.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.win;
2 |
3 | import com.sun.jna.Callback;
4 | import com.sun.jna.Library;
5 | import com.sun.jna.Native;
6 | import com.sun.jna.Pointer;
7 | import com.sun.jna.WString;
8 |
9 | public interface Handle extends Library{
10 | Handle INSTANCE = (Handle)Native.loadLibrary("libwincocoainput", Handle.class);
11 |
12 | void set_focus(int flag);
13 | void initialize(
14 | long window,
15 | PreeditCallback paramDrawCallback,
16 | DoneCallback paramDoneCallback,
17 | RectCallback paramRectCallback,
18 | Callback log,
19 | Callback error,
20 | Callback debug
21 | );
22 |
23 | public static interface PreeditCallback extends Callback{
24 | void invoke(WString str,int cursor,int length);
25 | }
26 | /*public static interface DrawCallback extends Callback {
27 | Pointer invoke(int param1Int1, int param1Int2, int param1Int3, short param1Short, boolean param1Boolean, String param1String, WString param1WString, int param1Int4, int param1Int5, int param1Int6);
28 | }*/
29 | public static interface DoneCallback extends Callback {
30 | void invoke(WString str);
31 | }
32 |
33 | public static interface RectCallback extends Callback{
34 | int invoke(Pointer p);
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/win/Logger.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.win;
2 |
3 | import org.apache.logging.log4j.Level;
4 | import org.apache.logging.log4j.LogManager;
5 |
6 | import com.sun.jna.Callback;
7 |
8 | public class Logger {
9 |
10 | public static void log(String msg,Object...data){
11 | LogManager.getLogger("CocoaInputWin:Java").log( Level.INFO,msg, data);
12 | }
13 |
14 | public static void error(String msg,Object...data){
15 | LogManager.getLogger("CocoaInputWin:Java").log( Level.ERROR,msg, data);
16 | }
17 |
18 | public static void debug(String msg,Object...data){
19 | LogManager.getLogger("CocoaInputWin:Java").log( Level.DEBUG,msg, data);
20 |
21 | }
22 |
23 | public static Callback clangLog = new Callback() {
24 | public void invoke(String msg) {
25 | LogManager.getLogger("CocoaInputWin:Clang").log(Level.INFO, msg);
26 | }
27 | };
28 | public static Callback clangError = new Callback() {
29 | public void invoke(String msg) {
30 | LogManager.getLogger("CocoaInputWin:Clang").log(Level.ERROR, msg);
31 | }
32 | };
33 | public static Callback clangDebug = new Callback() {
34 | public void invoke(String msg) {
35 | LogManager.getLogger("CocoaInputWin:Clang").log(Level.DEBUG, msg);
36 | }
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/x11/Logger.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.x11;
2 |
3 | import org.apache.logging.log4j.Level;
4 | import org.apache.logging.log4j.LogManager;
5 |
6 | import com.sun.jna.Callback;
7 |
8 | public class Logger {
9 |
10 | public static void log(String msg,Object...data){
11 | LogManager.getLogger("CocoaInputX11:Java").log( Level.INFO,msg, data);
12 | }
13 |
14 | public static void error(String msg,Object...data){
15 | LogManager.getLogger("CocoaInputX11:Java").log( Level.ERROR,msg, data);
16 | }
17 |
18 | public static void debug(String msg,Object...data){
19 | LogManager.getLogger("CocoaInputX11:Java").log( Level.DEBUG,msg, data);
20 |
21 | }
22 |
23 | public static Callback clangLog = new Callback() {
24 | public void invoke(String msg) {
25 | LogManager.getLogger("CocoaInputX11:Clang").log(Level.INFO, msg);
26 | }
27 | };
28 | public static Callback clangError = new Callback() {
29 | public void invoke(String msg) {
30 | LogManager.getLogger("CocoaInputX11:Clang").log(Level.ERROR, msg);
31 | }
32 | };
33 | public static Callback clangDebug = new Callback() {
34 | public void invoke(String msg) {
35 | LogManager.getLogger("CocoaInputX11:Clang").log(Level.DEBUG, msg);
36 | }
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/fabric/java/jp/axer/cocoainput/loader/FabricLoader.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.loader;
2 |
3 | import net.fabricmc.api.ClientModInitializer;
4 | import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
5 | import jp.axer.cocoainput.CocoaInput;
6 | import jp.axer.cocoainput.util.ModLogger;
7 | import jp.axer.cocoainput.util.FCConfig;
8 | import net.minecraft.client.gui.screens.Screen;
9 |
10 | public class FabricLoader implements ClientModInitializer {
11 | public static FabricLoader instance;
12 | public CocoaInput cocoainput;
13 | @Override
14 | public void onInitializeClient() {
15 | FabricLoader.instance=this;
16 | }
17 | public void onWindowLaunched(){
18 | this.cocoainput=new CocoaInput("Fabric",null);
19 | ModLogger.log("Fabric config setup");
20 | ModLogger.log("Config path:"+net.fabricmc.loader.api.FabricLoader.getInstance().getConfigDir().resolve("cocoainput.json").toString());
21 | FCConfig.init("cocoainput",net.fabricmc.loader.api.FabricLoader.getInstance().getConfigDir().resolve("cocoainput.json"), FCConfig.class);
22 | CocoaInput.config=new FCConfig();
23 | ModLogger.log("ConfigPack:"+CocoaInput.config.isAdvancedPreeditDraw()+" "+CocoaInput.config.isNativeCharTyped());
24 | }
25 |
26 | public void onChangeScreen(Screen sc){
27 | if(this.cocoainput==null){
28 | this.onWindowLaunched();
29 | return;
30 | }
31 | this.cocoainput.distributeScreen(sc);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/darwin/DarwinController.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.darwin;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | import jp.axer.cocoainput.CocoaInput;
6 | import jp.axer.cocoainput.plugin.CocoaInputController;
7 | import jp.axer.cocoainput.plugin.IMEOperator;
8 | import jp.axer.cocoainput.plugin.IMEReceiver;
9 | import jp.axer.cocoainput.util.ModLogger;
10 | import net.minecraft.client.gui.screens.Screen;
11 |
12 | public class DarwinController implements CocoaInputController {
13 | public DarwinController() throws Exception {
14 | CocoaInput.copyLibrary("libcocoainput.dylib", "darwin/libcocoainput.dylib");
15 | Handle.INSTANCE.initialize(CallbackFunction.Func_log, CallbackFunction.Func_error, CallbackFunction.Func_debug);
16 | ModLogger.log("DarwinController has been initialized.");
17 | }
18 |
19 | @Override
20 | public IMEOperator generateIMEOperator(IMEReceiver ime) {
21 | return new DarwinIMEOperator(ime);
22 | }
23 |
24 |
25 | @Override
26 | public void screenOpenNotify(Screen gui) {
27 | try {
28 | Field wrapper = gui.getClass().getField("wrapper");
29 | wrapper.setAccessible(true);
30 | if (wrapper.get(gui) instanceof IMEReceiver)
31 | return;
32 | } catch (Exception e) {/* relax */}
33 | Handle.INSTANCE.refreshInstance();//GUIの切り替えでIMの使用をoffにする
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # CocoaInput
2 | Support IME - Input Method Editor(Japanese,Chinese,Korean) in Minecraft on Multi-platforms(macOS, Windows, X11).
3 |
4 | ## Compiling
5 | 1. Clone git repository
6 | ```Bash
7 | git clone https://github.com/Axeryok/CocoaInput.git
8 | cd CocoaInput
9 | ```
10 | 2. Compile native library
11 | CocoaInput needs native-platform libraries to work.
12 | To compile them, run one of below scripts which is your platform.
13 | - build_lib_for_mac.sh - For macOS
14 | - build_lib_for_x11.sh - For Linux
15 | - build_lib_for_win.sh - For Windows
16 | - (build_lib_all.sh - For all platform, You should create remote_build.sh to build macOS lib remotely.)
17 | 3. Compile Forge Mod
18 | Type below command.Forge mod will be located in "fabric/build/libs".
19 | ```Bash
20 | ./gradlew build
21 | ```
22 | 4. Compile Fabric Mod
23 | Type below command.Fabric mod will be located in "fabric/build/libs".
24 | ```Bash
25 | cd fabric
26 | ./gradlew build
27 | ```
28 |
29 | ## Installing
30 | CocoaInput official binaries has been distributed on https://www.curseforge.com/minecraft/mc-mods/cocoainput .
31 | Get jar from above URL or trying ”Compiling" task.
32 | Place it in your mods directory.
33 |
34 | CocoaInput requires MinecraftForge or Fabric.
35 |
36 | This mod uses Java Native Access (Apache Licence2) and binuary for Minecraft1.7.10 contains it.
37 |
38 | ## License
39 | Minecraft Mod Public License Japanese Transration
40 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/DataManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // DataManager.h
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | #import "MinecraftView.h"
13 |
14 | @interface DataManager : NSObject
15 |
16 | @property BOOL hasPreeditText;
17 | @property BOOL isSentedInsertText;
18 | @property BOOL isBeforeActionSetMarkedText;
19 | //@property void (*insertText)(const char*, const int, const int);
20 | //@property void (*setMarkedText)(const char*, const int, const int, const int, const int);
21 | //@property float* (*firstRectForCharacterRange)(void);
22 |
23 |
24 |
25 |
26 | @property NSMutableDictionary* dic;
27 | @property MinecraftView* activeView;
28 | @property NSView* glfwView;
29 | + (instancetype)sharedManager;
30 | - (void) modifyGLFWView;
31 |
32 | //機能上書き
33 | - (void)keyDown:(NSEvent*)theEvent;
34 | - (void)interpretKeyEvents:(NSArray*)eventArray;
35 |
36 | //形式上
37 | - (void)org_keyDown:(NSEvent*)theEvent;
38 | - (void)org_unmarkText;
39 | - (void)org_interpretKeyEvents:(NSArray*)eventArray;
40 | - (NSRect)org_firstRectForCharacterRange:(NSRange)aRange
41 | actualRange:(NSRangePointer)actualRange;
42 | - (void)org_insertText:(id)aString replacementRange:(NSRange)replacementRange;
43 | - (void)org_setMarkedText:(id)aString
44 | selectedRange:(NSRange)selectedRange
45 | replacementRange:(NSRange)replacementRange ;
46 | @end
47 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/darwin/CallbackFunction.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.darwin;
2 |
3 | import com.sun.jna.Callback;
4 | import com.sun.jna.Pointer;
5 | import jp.axer.cocoainput.util.ModLogger;
6 | import org.apache.logging.log4j.Level;
7 | import org.apache.logging.log4j.LogManager;
8 |
9 | public class CallbackFunction {
10 | //used to interact Objective-C code
11 | interface Func_insertText extends Callback {
12 | void invoke(String str, int position, int length);
13 | }
14 |
15 | interface Func_setMarkedText extends Callback {
16 | void invoke(String str, int position1, int length1, int position2, int length2);
17 | }
18 |
19 | interface Func_firstRectForCharacterRange extends Callback {
20 | Pointer invoke();
21 | }
22 |
23 | //used to provide Objective-C with logging way
24 | public static Callback Func_log = new Callback() {
25 | public void invoke(String msg) {
26 | LogManager.getLogger("CocoaInput:ObjC").log(Level.INFO, msg);
27 | }
28 | };
29 | public static Callback Func_error = new Callback() {
30 | public void invoke(String msg) {
31 | LogManager.getLogger("CocoaInput:ObjC").log(Level.ERROR, msg);
32 | }
33 | };
34 | public static Callback Func_debug = new Callback() {
35 | public void invoke(String msg) {
36 | if (ModLogger.debugMode) {
37 | LogManager.getLogger("CocoaInput:ObjC").log(Level.DEBUG, msg);
38 | }
39 | }
40 | };
41 | }
--------------------------------------------------------------------------------
/libcocoainput/x11/libx11cocoainput.h:
--------------------------------------------------------------------------------
1 | //#include
2 | #include
3 | //#include "internal.h"
4 | //#include "x11_platform.h"
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "logger.h"
14 |
15 | typedef int GLFWbool;
16 |
17 | typedef struct _GLFWwindowX11
18 | {
19 | Colormap colormap;
20 | Window handle;
21 | //Window parent;
22 | XIC ic;
23 |
24 | GLFWbool overrideRedirect;
25 | GLFWbool iconified;
26 | GLFWbool maximized;
27 |
28 | // Whether the visual supports framebuffer transparency
29 | GLFWbool transparent;
30 |
31 | // Cached position and size used to filter out duplicate events
32 | int width, height;
33 | int xpos, ypos;
34 |
35 | // The last received cursor position, regardless of source
36 | int lastCursorPosX, lastCursorPosY;
37 | // The last position the cursor was warped to by GLFW
38 | int warpCursorPosX, warpCursorPosY;
39 |
40 | // The time of the last KeyPress event per keycode, for discarding
41 | // duplicate key events generated for some keys by ibus
42 | Time keyPressTimes[256];
43 |
44 | } _GLFWwindowX11;
45 |
46 |
47 | void initialize(
48 | long waddr,
49 | long xw,
50 | int*(*c_draw)(int,int,int,short,int,char*,wchar_t*,int,int,int),
51 | void(*c_done)(),
52 | LogFunction log,
53 | LogFunction error,
54 | LogFunction debug
55 | );
56 |
57 |
58 |
59 |
60 | void set_focus(int flag);
61 |
--------------------------------------------------------------------------------
/src/forge/resources/META-INF/accesstransformer.cfg:
--------------------------------------------------------------------------------
1 | public net.minecraft.client.gui.components.EditBox f_94092_ #font
2 | public net.minecraft.client.gui.components.EditBox f_94096_ #bordered
3 | public net.minecraft.client.gui.components.EditBox f_94093_ #value
4 | public net.minecraft.client.gui.components.EditBox f_94095_ #frame
5 | public net.minecraft.client.gui.components.EditBox m_94174_(Ljava/lang/String;)V #onValueChange
6 |
7 |
8 | public net.minecraft.client.gui.screens.inventory.SignEditScreen f_99256_ #line
9 | public net.minecraft.client.gui.screens.inventory.SignEditScreen f_99254_ #sign
10 | public net.minecraft.client.gui.screens.inventory.SignEditScreen f_99258_ #messages
11 | public net.minecraft.client.gui.screens.inventory.SignEditScreen f_99257_ #signField
12 | public net.minecraft.client.gui.screens.inventory.SignEditScreen f_99255_ #frame
13 |
14 |
15 | public net.minecraft.client.gui.screens.inventory.BookEditScreen m_98158_(Ljava/lang/String;)V #setCurrentPage
16 | public net.minecraft.client.gui.screens.inventory.BookEditScreen m_98191_()Ljava.lang.String; #getCurrentPage
17 | public net.minecraft.client.gui.screens.inventory.BookEditScreen f_98071_ #title
18 | public net.minecraft.client.gui.screens.inventory.BookEditScreen f_98067_ #isSigning
19 | public net.minecraft.client.gui.screens.inventory.BookEditScreen f_98072_ #pageEdit
20 | public net.minecraft.client.gui.screens.inventory.BookEditScreen f_98073_ #titleEdit
21 | public net.minecraft.client.gui.screens.inventory.BookEditScreen f_98068_ #frameTick
22 |
23 | public net.minecraft.client.gui.screens.Screen f_96547_ #font
24 |
25 | public net.minecraft.client.KeyboardHandler m_90889_(JII)V #charTyped
26 |
--------------------------------------------------------------------------------
/src/fabric/resources/cocoainput.accesswidener:
--------------------------------------------------------------------------------
1 | accessWidener v1 named
2 | accessible field net/minecraft/client/gui/components/EditBox font Lnet/minecraft/client/gui/Font;
3 | accessible field net/minecraft/client/gui/components/EditBox bordered Z
4 | accessible field net/minecraft/client/gui/components/EditBox value Ljava/lang/String;
5 | accessible field net/minecraft/client/gui/components/EditBox frame I
6 | accessible method net/minecraft/client/gui/components/EditBox onValueChange (Ljava/lang/String;)V
7 | accessible field net/minecraft/client/gui/screens/inventory/SignEditScreen line I
8 | accessible field net/minecraft/client/gui/screens/inventory/SignEditScreen frame I
9 | accessible field net/minecraft/client/gui/screens/inventory/SignEditScreen sign Lnet/minecraft/world/level/block/entity/SignBlockEntity;
10 | accessible field net/minecraft/client/gui/screens/inventory/SignEditScreen messages [Ljava/lang/String;
11 | accessible field net/minecraft/client/gui/screens/inventory/SignEditScreen signField Lnet/minecraft/client/gui/font/TextFieldHelper;
12 | accessible method net/minecraft/client/gui/screens/inventory/BookEditScreen setCurrentPageText (Ljava/lang/String;)V
13 | accessible method net/minecraft/client/gui/screens/inventory/BookEditScreen getCurrentPageText ()Ljava/lang/String;
14 | accessible field net/minecraft/client/gui/screens/inventory/BookEditScreen title Ljava/lang/String;
15 | accessible field net/minecraft/client/gui/screens/inventory/BookEditScreen isSigning Z
16 | accessible field net/minecraft/client/gui/screens/inventory/BookEditScreen frameTick I
17 | accessible field net/minecraft/client/gui/screens/inventory/BookEditScreen pageEdit Lnet/minecraft/client/gui/font/TextFieldHelper;
18 | accessible field net/minecraft/client/gui/screens/inventory/BookEditScreen titleEdit Lnet/minecraft/client/gui/font/TextFieldHelper;
19 | accessible field net/minecraft/client/gui/screens/Screen font Lnet/minecraft/client/gui/Font;
20 | accessible method net/minecraft/client/KeyboardHandler charTyped (JII)V
21 |
--------------------------------------------------------------------------------
/src/forge/resources/META-INF/mods.toml:
--------------------------------------------------------------------------------
1 | # This is an example mods.toml file. It contains the data relating to the loading mods.
2 | # There are several mandatory fields (#mandatory), and many more that are optional (#optional).
3 | # The overall format is standard TOML format, v0.5.0.
4 | # Note that there are a couple of TOML lists in this file.
5 | # Find more information on toml format here: https://github.com/toml-lang/toml
6 | # The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
7 | modLoader="javafml" #mandatory
8 | # A version range to match for said mod loader - for regular FML @Mod it will be the forge version
9 | loaderVersion="[25,)" #mandatory (24 is current forge version)
10 | # A URL to refer people to when problems occur with this mod
11 | issueTrackerURL="https://github.com/Axeryok/CocoaInput/issues" #optional
12 | # License
13 | license="Minecraft Mod Public License Japanese Transration" #mandatory
14 | # A list of mods - how many allowed here is determined by the individual mod loader
15 | [[mods]] #mandatory
16 | # The modid of the mod
17 | modId="cocoainput" #mandatory
18 | # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
19 | version="${file.jarVersion}" #mandatory
20 | # A display name for the mod
21 | displayName="CocoaInput" #mandatory
22 | # A URL to query for updates for this mod. See the JSON update specification
23 | #updateJSONURL="http://myurl.me/" #optional
24 | # A URL for the "homepage" for this mod, displayed in the mod UI
25 | displayURL="https://axer.jp/" #optional
26 | # A file name (in the root of the mod JAR) containing a logo for display
27 | #logoFile="logo.png" #optional
28 | # A text field displayed in the mod UI
29 | credits="This mod uses JavaNativeAccess(Apache License2)." #optional
30 | # A text field displayed in the mod UI
31 | authors="Axeryok" #optional
32 | # The description text for the mod (multi line!) (#mandatory)
33 | description='''
34 | Support IME input on macOS,Windows,X11(Linux).
35 | '''
36 |
--------------------------------------------------------------------------------
/src/forge/java/jp/axer/cocoainput/loader/ForgeLoader.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.loader;
2 |
3 | import jp.axer.cocoainput.CocoaInput;
4 | import jp.axer.cocoainput.util.ModLogger;
5 | import jp.axer.cocoainput.util.FCConfig;
6 | import net.minecraftforge.client.event.ScreenOpenEvent;
7 | import net.minecraftforge.common.MinecraftForge;
8 | import net.minecraftforge.eventbus.api.SubscribeEvent;
9 | import net.minecraftforge.client.ConfigGuiHandler;
10 |
11 | import net.minecraftforge.fml.ModList;
12 | import net.minecraftforge.fml.ModLoadingContext;
13 | import net.minecraftforge.fml.common.Mod;
14 | import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
15 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
16 | import net.minecraftforge.fml.loading.FMLPaths;
17 |
18 | @Mod("cocoainput")
19 | public class ForgeLoader {
20 | private CocoaInput instance;
21 |
22 | public ForgeLoader(){
23 | FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
24 | MinecraftForge.EVENT_BUS.register(this);
25 |
26 | }
27 |
28 | private void setup(final FMLCommonSetupEvent event) {
29 | this.instance=new CocoaInput("MinecraftForge",ModList.get().getModFileById("cocoainput").getFile().getFilePath().toString());
30 | ModLogger.log("Forge config setup");
31 | ModLogger.log("Config path:"+FMLPaths.CONFIGDIR.get().resolve("cocoainput.json").toString());
32 | FCConfig.init("cocoainput",FMLPaths.CONFIGDIR.get().resolve("cocoainput.json"), FCConfig.class);
33 | ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class, ()->new ConfigGuiHandler.ConfigGuiFactory((mc,modListScreen)->new FCConfig().getScreen(modListScreen)));
34 | CocoaInput.config=new FCConfig();
35 | ModLogger.log("ConfigPack:"+CocoaInput.config.isAdvancedPreeditDraw()+" "+CocoaInput.config.isNativeCharTyped());
36 | }
37 | @SubscribeEvent
38 | public void didChangeGui(ScreenOpenEvent event) {
39 | this.instance.distributeScreen(event.getScreen());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/wrapper/EditBoxWrapper.java:
--------------------------------------------------------------------------------
1 |
2 | package jp.axer.cocoainput.wrapper;
3 |
4 | import jp.axer.cocoainput.CocoaInput;
5 | import jp.axer.cocoainput.plugin.IMEOperator;
6 | import jp.axer.cocoainput.plugin.IMEReceiver;
7 | import jp.axer.cocoainput.util.ModLogger;
8 | import jp.axer.cocoainput.util.Rect;
9 | import net.minecraft.client.gui.components.EditBox;
10 | import net.minecraft.network.chat.TextComponent;
11 |
12 | public class EditBoxWrapper extends IMEReceiver {
13 | private IMEOperator myIME;
14 | private EditBox owner;
15 |
16 | public EditBoxWrapper(EditBox field) {
17 | ModLogger.debug("EditBox init: " + field.hashCode());
18 | owner = field;
19 | myIME = CocoaInput.getController().generateIMEOperator(this);
20 | }
21 |
22 | public void setCanLoseFocus(boolean newParam) {
23 | if (!newParam) setFocused(true);
24 | }
25 |
26 | public void setFocused(boolean newParam) {
27 | owner.setFormatter( ((abc,def) -> new TextComponent(abc).getVisualOrderText() ));
28 | myIME.setFocused(newParam);
29 | }
30 |
31 |
32 | public void updateCursorCounter() {
33 | if (cursorVisible) owner.frame++;
34 | }
35 |
36 | protected void setText(String text) {
37 | owner.value=text;
38 | }
39 |
40 | protected String getText() {
41 | return owner.value;
42 | }
43 |
44 | protected void setCursorInvisible() {
45 | owner.frame=6;
46 | }
47 |
48 | protected int getCursorPos() {
49 | return owner.getCursorPosition();
50 | }
51 |
52 | protected void setCursorPos(int p) {
53 | owner.moveCursorTo(p);
54 | }
55 |
56 | protected void setSelectionPos(int p) {
57 | owner.setHighlightPos(p);
58 | }
59 |
60 |
61 | @Override
62 | public Rect getRect() {
63 | return new Rect(//{x,y}
64 | (owner.font.width(owner.getValue().substring(0, originalCursorPosition)) + (owner.bordered ? owner.x + 4 : owner.x)),
65 | (owner.font.lineHeight + (owner.bordered ? owner.y + (owner.getHeight() - 8) / 2 : owner.y)),
66 | owner.getWidth(),
67 | owner.getHeight()
68 |
69 | );
70 | }
71 |
72 | protected void notifyParent(String text) {
73 | // TODO 自動生成されたメソッド・スタブ
74 | owner.onValueChange(text);
75 |
76 | }
77 |
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Minecraft Mod Public License Japanese Transration (MMPL_J)
2 |
3 | Version 1.0.1
4 |
5 |
6 | (A.序文)
7 |
8 | 一条 [MMPL_J]
9 | 本ライセンスは、"Minecraft Mod Public License"(以下MMPL) (原文:http://tsoft-web.com/nokiyen/minecraft/modding/MMPL)の日本語訳及びその拡張であり、"Minecraft Mod Public License Japanese Transration"(以下MMPL_J)と呼称する。
10 |
11 | 二条 [構成と効力]
12 | MMPL_JはA.序文、B.翻訳からなる。MMPL_Jをライセンスとして使用する場合、特に表示のない限りA及びBの両方がライセンスとして効力を持つ。
13 |
14 | 三条 [Bの効力]
15 | B.翻訳は、MMPLの翻訳部分であり、MMPLと同等の意味内容を持つ。B.翻訳のいかなる翻訳間違えも無効となり、MMPLの該当部分が代わりに適用される。
16 |
17 | 四条 [版]
18 | B.翻訳はMMPL Version1.0.1の翻訳である。
19 |
20 |
21 | (B.翻訳)
22 |
23 | 0. 定義
24 | --------
25 |
26 | Minecraft: Mojang ABがライセンスを持つMinecraftというゲームの複製を指す。
27 |
28 | 利用者: 以下のいずれかの方法で当該ソフトウェアに関わるすべての者。
29 | - プレイする
30 | - デコンパイルする
31 | - リコンパイルまたコンパイルする
32 | - 改変する
33 | - 配布する
34 |
35 | Mod: ゲーム拡張のためのコードであり、本ライセンスでは、ソース形式またはバイナリ形式の、それ単体で入手されるもの、より大きな配布の一部分、またはオリジナルのソースもしくは改変されたソースをコンパイルしたものを示す。
36 |
37 | 依存: 当該modが正しく機能するために必要とされるコード。これは、当該コードをコンパイルするのに必要な依存、及び当該modが機能するために明示的または暗黙に必要とされるすべてのファイルまたは改変を含む。
38 |
39 |
40 | 1. 範囲
41 | --------
42 |
43 | 本ライセンスは当該modのすべての利用者に適用される。前提条件として、利用者は法的に正しく取得されたMinecraftの複製を所持していなければならない。
44 |
45 |
46 | 2. 責任
47 | --------
48 |
49 | 当該modは、暗黙にせよそうでないにせよ、"現状のもの"が保証なしに提供される。当該modの権利所有者は当該modの利用により受けたいかなる損害に対しても責任を持たない。当該modはMinecraftというゲームの根本的な部分を変えるものであり、Minecraftの一部分が当該modが導入されたことにより機能しない場合がある。当該modの利用や誤用により引き起こされるすべての損害は、利用者が負うこととなる。
50 |
51 |
52 | 3. プレイする権利
53 | --------
54 |
55 | 利用者は、制限なしに、当該modをクライアントまたはサーバに導入し、プレイすることができる。
56 |
57 |
58 | 4. 改変する権利
59 | --------
60 |
61 | 利用者は、当該modのソースコードをデコンパイルする、デコンパイルされたまたはオリジナルのソースコードを見る、及びそれを改変する権利を持つ。
62 |
63 |
64 | 5. 引用する権利
65 | --------
66 |
67 | 利用者は、当該modのコードを引用する、すなわち、当該modのクラスまたはインターフェースを継承またはインスタンス化する、当該modのオブジェクトを参照する、及び当該modの関数をコールする権利を持つ。こうしたコードは"引用"コードとして知られ、当該modと異なるライセンスの元で保障されうる。
68 |
69 |
70 | 6. オリジナルないし改変された著作権物の配布
71 | --------
72 |
73 | 当該mod全体が、様々な形式において、配布に関する権利に従う。様々な形式とは以下を含む。
74 | - オリジナルの、バイナリまたはソース形式の当該modファイル
75 | - これらのバイナリまたはソースファイルを改変したもの、及びソースを改変することにより得られたバイナリ
76 | - 当該modのソースまたはバイナリファイルへのパッチ
77 | - 当該modのバイナリまたはソースファイルの一部の複製
78 |
79 | 利用者は、当該modの一部分または全体を再配布する、もしくは配布物に含めて再配布することができる。
80 |
81 | バイナリファイルを配布する場合は、利用者は当該modのソースまたは改変したソース全体を入手する手段を無償で提供しなければならない。
82 |
83 | 当該modの配布物のライセンスは、すべてMMPLのままでなければならない。
84 |
85 | 当該modが他のModやクラスに持つ依存はすべて、現行版のMMPLに相当する条件のもとでライセンスが適用されなければならない。ただし、MinecraftのコードとModを読みこむフレームワーク(ModLoader、ModLoaderMP, Bukkitなど)についてはこの限りでない。
86 |
87 | バイナリ及びソースを改変したもの、並びに当該modを複製して得られた部分を含むファイルは、本ライセンスの条項の元で配布されなければならない。
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/wrapper/SignEditScreenWrapper.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.wrapper;
2 |
3 | import jp.axer.cocoainput.CocoaInput;
4 | import jp.axer.cocoainput.plugin.IMEOperator;
5 | import jp.axer.cocoainput.plugin.IMEReceiver;
6 | import jp.axer.cocoainput.util.ModLogger;
7 | import jp.axer.cocoainput.util.Rect;
8 | import jp.axer.cocoainput.util.WrapperUtil;
9 | import net.minecraft.world.level.block.StandingSignBlock;
10 | import net.minecraft.client.gui.Font;
11 | import net.minecraft.client.gui.screens.inventory.SignEditScreen;
12 | import net.minecraft.network.chat.TextComponent;
13 |
14 | public class SignEditScreenWrapper extends IMEReceiver {
15 | private SignEditScreen owner;
16 | private IMEOperator myIME;
17 |
18 |
19 | public SignEditScreenWrapper(SignEditScreen field) {
20 | ModLogger.debug("SignEditScreen init: " + field.hashCode());
21 | owner = field;
22 | myIME = CocoaInput.getController().generateIMEOperator(this);
23 | myIME.setFocused(true);
24 | }
25 |
26 | protected void setText(String text) {
27 | owner.sign.setMessage(owner.line,new TextComponent(text));
28 | String [] util = owner.messages;
29 | util[owner.line]=text;
30 | }
31 |
32 | protected String getText() {
33 | return owner.sign.getMessage(owner.line,false).getString();
34 | }
35 |
36 | protected void setCursorInvisible() {
37 | owner.frame=6;
38 | } //TODO
39 |
40 | protected int getCursorPos() {
41 | return owner.signField.getCursorPos();
42 | }
43 |
44 | protected void setCursorPos(int p) {
45 | owner.signField.setCursorPos(p,true);
46 | }
47 |
48 | protected void setSelectionPos(int p) {
49 | owner.signField.setSelectionRange(p,p);
50 | }
51 |
52 |
53 | @Override
54 | public Rect getRect() {
55 |
56 | Font fontRendererObj = null;
57 | try {
58 | fontRendererObj = WrapperUtil.makeFont(owner);
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | }
62 | float y = 91 + (owner.line - 1) * (10);
63 | if (!(owner.sign.getBlockState().getBlock() instanceof StandingSignBlock)) {
64 | y += 30;
65 | }
66 | return new Rect(
67 | owner.width/2+fontRendererObj.width(owner.sign.getMessage(owner.line,false).toString().substring(0, originalCursorPosition))/2,
68 | // owner.width / 2 + fontRendererObj.width(owner.sign.getMessage(owner.line,false).getString()) / 2,
69 | y,
70 | 0,
71 | 0
72 | );
73 | }
74 | public int renewCursorCounter() {
75 | return owner.frame+(cursorVisible?1:0);
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/fabric/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/forge/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/darwin/DarwinIMEOperator.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.darwin;
2 |
3 | import com.sun.jna.Memory;
4 | import com.sun.jna.Pointer;
5 | import jp.axer.cocoainput.CocoaInput;
6 | import jp.axer.cocoainput.arch.darwin.CallbackFunction.Func_firstRectForCharacterRange;
7 | import jp.axer.cocoainput.arch.darwin.CallbackFunction.Func_insertText;
8 | import jp.axer.cocoainput.arch.darwin.CallbackFunction.Func_setMarkedText;
9 | import jp.axer.cocoainput.plugin.IMEOperator;
10 | import jp.axer.cocoainput.plugin.IMEReceiver;
11 | import jp.axer.cocoainput.util.ModLogger;
12 | import jp.axer.cocoainput.util.Rect;
13 |
14 | import java.util.UUID;
15 |
16 | public class DarwinIMEOperator implements IMEOperator {
17 | IMEReceiver owner;
18 | String uuid;
19 | Func_insertText insertText_p;
20 | Func_setMarkedText setMarkedText_p;
21 | Func_firstRectForCharacterRange firstRectForCharacterRange_p;
22 | boolean isFocused = false;
23 |
24 | public DarwinIMEOperator(IMEReceiver field) {
25 | this.owner = field;
26 | uuid = UUID.randomUUID().toString();
27 | insertText_p = new Func_insertText() {
28 | @Override
29 | public void invoke(String str, int position, int length) {
30 | ModLogger.debug("Textfield " + uuid + " received inserted text.");
31 | owner.insertText(str, position, length);
32 | }
33 | };
34 | setMarkedText_p = new Func_setMarkedText() {
35 | @Override
36 | public void invoke(String str, int position1, int length1,
37 | int position2, int length2) {
38 | ModLogger.debug("MarkedText changed at " + uuid + ".");
39 | owner.setMarkedText(str, position1, length1, position2, length2);
40 | ;
41 | }
42 |
43 | };
44 | firstRectForCharacterRange_p = new Func_firstRectForCharacterRange() {
45 |
46 | @Override
47 | public Pointer invoke() {
48 | ModLogger.debug("Called to determine where to draw.");
49 | Rect point = owner.getRect();
50 | float[] buff;
51 | if (point == null) {
52 | buff = new float[]{0, 0, 0, 0};
53 | } else {
54 | buff = new float[]{point.getX(), point.getY(), point.getWidth(), point.getHeight()};
55 | }
56 | double factor = CocoaInput.getScreenScaledFactor();
57 | buff[0] *= factor;
58 | buff[1] *= factor;
59 | buff[2] *= factor;
60 | buff[3] *= factor;
61 |
62 | Pointer ret = new Memory(Float.BYTES * 4);
63 | ret.write(0, buff, 0, 4);
64 | return ret;
65 | }
66 |
67 | };
68 | ModLogger.log("IMEOperator addInstance: " + uuid);
69 | Handle.INSTANCE.addInstance(uuid, insertText_p, setMarkedText_p, firstRectForCharacterRange_p);
70 | }
71 |
72 | public void discardMarkedText() {
73 | Handle.INSTANCE.discardMarkedText(uuid);
74 | }
75 |
76 | public void removeInstance() {
77 | Handle.INSTANCE.removeInstance(uuid);
78 | }
79 |
80 | public void setFocused(boolean yn) {
81 | if (yn != isFocused) {
82 | ModLogger.log("IMEOperator.setFocused: " + (yn ? "true" : "false"));
83 | Handle.INSTANCE.setIfReceiveEvent(uuid, yn ? 1 : 0);
84 | isFocused = yn;
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/win/WinController.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.win;
2 | import java.io.IOException;
3 | import java.lang.reflect.Field;
4 |
5 | import com.sun.jna.Pointer;
6 | import com.sun.jna.WString;
7 |
8 | import jp.axer.cocoainput.CocoaInput;
9 | import jp.axer.cocoainput.arch.win.Handle.DoneCallback;
10 | import jp.axer.cocoainput.arch.win.Handle.PreeditCallback;
11 | import jp.axer.cocoainput.arch.win.Handle.RectCallback;
12 | import jp.axer.cocoainput.plugin.CocoaInputController;
13 | import jp.axer.cocoainput.plugin.IMEOperator;
14 | import jp.axer.cocoainput.plugin.IMEReceiver;
15 | import jp.axer.cocoainput.util.Rect;
16 | import net.minecraft.client.Minecraft;
17 | import net.minecraft.client.gui.screens.Screen;
18 |
19 | public class WinController implements CocoaInputController {
20 |
21 | static WinIMEOperator focusedOperator = null;
22 |
23 | PreeditCallback pc = new PreeditCallback() {
24 | @Override
25 | public void invoke(WString str, int cursor, int length) {
26 | if(focusedOperator!=null) {
27 | Logger.log("marked "+str.toString()+" "+cursor+" "+length);
28 | focusedOperator.owner.setMarkedText(str.toString(), cursor, length,0,0);
29 | }
30 | }
31 | };
32 | DoneCallback dc = new DoneCallback() {
33 | @Override
34 | public void invoke(WString str) {
35 | if(focusedOperator!=null) {
36 | Logger.log("done ("+str.toString()+")");
37 | focusedOperator.owner.insertText(str.toString(), 0, 0);
38 | }
39 | }
40 | };
41 |
42 | RectCallback rc = new RectCallback() {
43 | @Override
44 | public int invoke(Pointer ret) {
45 | if(focusedOperator!=null) {
46 | Logger.log("Rect callback");
47 | Rect point = focusedOperator.owner.getRect();
48 | float[] buff;
49 | if (point == null) {
50 | buff = new float[]{0, 0, 0, 0};
51 | } else {
52 | buff = new float[]{point.getX(), point.getY(), point.getWidth(), point.getHeight()};
53 | }
54 | double factor = CocoaInput.getScreenScaledFactor();
55 | buff[0] *= factor;
56 | buff[1] *= factor;
57 | buff[2] *= factor;
58 | buff[3] *= factor;
59 |
60 | ret.write(0, buff, 0, 4);
61 | return 0;
62 | }
63 | return 1;
64 | }
65 |
66 | };
67 |
68 | public WinController() {
69 | Logger.log("This is Windows Controller");
70 | try {
71 | CocoaInput.copyLibrary("libwincocoainput.dll", "win/libwincocoainput.dll");
72 | } catch (IOException e) {
73 | e.printStackTrace();
74 | }
75 | Handle.INSTANCE.initialize(org.lwjgl.glfw.GLFWNativeWin32.glfwGetWin32Window(Minecraft.getInstance().getWindow().getWindow()), pc, dc,rc, Logger.clangLog, Logger.clangError, Logger.clangDebug);
76 |
77 | }
78 |
79 |
80 | @Override
81 | public IMEOperator generateIMEOperator(IMEReceiver arg0) {
82 | return new WinIMEOperator(arg0);
83 | }
84 | @Override
85 | public void screenOpenNotify(Screen gui) {
86 | try {
87 | Field wrapper = gui.getClass().getField("wrapper");
88 | wrapper.setAccessible(true);
89 | if (wrapper.get(gui) instanceof IMEReceiver)
90 | return;
91 | } catch (Exception e) {
92 | /* relax */}
93 | if (WinController.focusedOperator != null) {
94 | //WinIMEOperator old=WinController.focusedOperator;
95 | //WinController.focusedOperator=null;
96 | WinController.focusedOperator.setFocused(false);
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/fabric/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'fabric-loom' version '0.10-SNAPSHOT'
3 | id 'maven-publish'
4 | }
5 |
6 | sourceCompatibility = JavaVersion.VERSION_17
7 | targetCompatibility = JavaVersion.VERSION_17
8 |
9 | archivesBaseName = project.archives_base_name
10 | version = project.mod_version
11 | group = project.maven_group
12 |
13 | loom {
14 | accessWidenerPath = file("../src/fabric/resources/cocoainput.accesswidener")
15 | }
16 |
17 | repositories {
18 | // Add repositories to retrieve artifacts from in here.
19 | // You should only use this when depending on other mods because
20 | // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
21 | // See https://docs.gradle.org/current/userguide/declaring_repositories.html
22 | // for more information about repositories.
23 | maven { url "https://maven.terraformersmc.com/releases/" }
24 | }
25 |
26 | dependencies {
27 | // To change the versions see the gradle.properties file
28 | minecraft "com.mojang:minecraft:${project.minecraft_version}"
29 | mappings minecraft.officialMojangMappings()
30 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
31 | // Fabric API. This is technically optional, but you probably want it anyway.
32 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
33 | modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
34 | // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
35 | // You may need to force-disable transitiveness on them.
36 | }
37 |
38 | processResources {
39 | inputs.property "version", project.version
40 |
41 | filesMatching("fabric.mod.json") {
42 | expand "version": project.version
43 | }
44 | }
45 |
46 | tasks.withType(JavaCompile).configureEach {
47 | // ensure that the encoding is set to UTF-8, no matter what the system default is
48 | // this fixes some edge cases with special characters not displaying correctly
49 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
50 | // If Javadoc is generated, this must be specified in that task too.
51 | it.options.encoding = "UTF-8"
52 |
53 | // Minecraft 1.17 (21w19a) upwards uses Java 16.
54 | it.options.release = 17
55 | }
56 |
57 | java {
58 | toolchain {
59 | languageVersion = JavaLanguageVersion.of(17)
60 | }
61 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
62 | // if it is present.
63 | // If you remove this line, sources will not be generated.
64 | sourceSets.main.java.srcDirs+=['../src/main']
65 | sourceSets.main.java.srcDirs+=['../src/fabric']
66 |
67 | sourceSets.main.resources.srcDirs+=['../src/main/resources']
68 | sourceSets.main.resources.srcDirs+=['../src/fabric/resources']
69 | withSourcesJar()
70 | }
71 |
72 | jar {
73 | from("LICENSE") {
74 | rename { "${it}_${project.archivesBaseName}"}
75 | }
76 | }
77 |
78 | // configure the maven publication
79 | publishing {
80 | publications {
81 | mavenJava(MavenPublication) {
82 | // add all the jars that should be included when publishing to maven
83 | artifact(remapJar) {
84 | builtBy remapJar
85 | }
86 | artifact(sourcesJar) {
87 | builtBy remapSourcesJar
88 | }
89 | }
90 | }
91 |
92 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
93 | repositories {
94 | // Add repositories to publish to here.
95 | // Notice: This block does NOT have the same function as the block in the top level.
96 | // The repositories here will be used for publishing your artifact, not for
97 | // retrieving dependencies.
98 | }
99 | }
100 |
101 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/CocoaInput.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.util.zip.ZipEntry;
9 | import java.util.zip.ZipFile;
10 |
11 | import org.apache.commons.io.IOUtils;
12 |
13 | import com.sun.jna.Platform;
14 |
15 | import jp.axer.cocoainput.arch.darwin.DarwinController;
16 | import jp.axer.cocoainput.arch.dummy.DummyController;
17 | import jp.axer.cocoainput.arch.win.WinController;
18 | import jp.axer.cocoainput.arch.x11.X11Controller;
19 | import jp.axer.cocoainput.plugin.CocoaInputController;
20 | import jp.axer.cocoainput.util.ConfigPack;
21 | import jp.axer.cocoainput.util.ModLogger;
22 | import net.minecraft.client.Minecraft;
23 | import net.minecraft.client.gui.screens.Screen;
24 |
25 | public class CocoaInput {
26 | private static CocoaInputController controller;
27 | private static String zipsource;
28 | public static ConfigPack config = ConfigPack.defaultConfig;
29 |
30 | public CocoaInput(String loader, String zipfile) {
31 | ModLogger.log("Modloader:" + loader);
32 | CocoaInput.zipsource = zipfile;
33 | try {
34 | if (Platform.isMac()) {
35 | CocoaInput.applyController(new DarwinController());
36 | } else if (Platform.isWindows()) {
37 | CocoaInput.applyController(new WinController());
38 | } else if (Platform.isX11()) {
39 | CocoaInput.applyController(new X11Controller());
40 | } else {
41 | ModLogger.log("CocoaInput cannot find appropriate Controller in running OS.");
42 | CocoaInput.applyController(new DummyController());
43 | }
44 | ModLogger.log("CocoaInput has been initialized.");
45 | } catch (Exception e) {
46 | e.printStackTrace();
47 | }
48 | }
49 |
50 | public static double getScreenScaledFactor() {
51 | return Minecraft.getInstance().getWindow().getGuiScale();
52 | }
53 |
54 | public static void applyController(CocoaInputController controller) throws IOException {
55 | CocoaInput.controller = controller;
56 | ModLogger.log("CocoaInput is now using controller:" + controller.getClass().toString());
57 | }
58 |
59 | public static CocoaInputController getController() {
60 | return CocoaInput.controller;
61 | }
62 |
63 | public void distributeScreen(Screen sc) {
64 | if (CocoaInput.getController() != null) {
65 | CocoaInput.getController().screenOpenNotify(sc);
66 | }
67 | }
68 |
69 | public static void copyLibrary(String libraryName, String libraryPath) throws IOException {
70 | InputStream libFile;
71 | if (zipsource == null) {//Fabric case
72 | libFile = CocoaInput.class.getResourceAsStream("/" + libraryPath);
73 | } else {
74 | try {//Modファイルを検出し、jar内からライブラリを取り出す
75 | ZipFile jarfile = new ZipFile(CocoaInput.zipsource);
76 | libFile = jarfile.getInputStream(new ZipEntry(libraryPath));
77 | } catch (FileNotFoundException e) {//存在しない場合はデバッグモードであるのでクラスパスからライブラリを取り出す
78 | ModLogger.log("Couldn't get library path. Is this debug mode?'");
79 | libFile = ClassLoader.getSystemResourceAsStream(libraryPath);
80 | }
81 | }
82 | File nativeDir = new File(Minecraft.getInstance().gameDirectory.getAbsolutePath().concat("/native"));
83 | File copyLibFile = new File(
84 | Minecraft.getInstance().gameDirectory.getAbsolutePath().concat("/native/" + libraryName));
85 | try {
86 | nativeDir.mkdir();
87 | FileOutputStream fos = new FileOutputStream(copyLibFile);
88 | copyLibFile.createNewFile();
89 | IOUtils.copy(libFile, fos);
90 | fos.close();
91 | } catch (IOException e1) {
92 | ModLogger.error("Attempted to copy library to ./native/" + libraryName + " but failed.");
93 | throw e1;
94 | }
95 | System.setProperty("jna.library.path", nativeDir.getAbsolutePath());
96 | ModLogger.log("CocoaInput has copied library to native directory.");
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/wrapper/BookEditScreenWrapper.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.wrapper;
2 |
3 | import java.util.List;
4 | import java.util.Optional;
5 |
6 | import jp.axer.cocoainput.CocoaInput;
7 | import jp.axer.cocoainput.plugin.IMEOperator;
8 | import jp.axer.cocoainput.plugin.IMEReceiver;
9 | import jp.axer.cocoainput.util.ModLogger;
10 | import jp.axer.cocoainput.util.Rect;
11 | import jp.axer.cocoainput.util.WrapperUtil;
12 | import net.minecraft.client.gui.Font;
13 | import net.minecraft.client.gui.screens.inventory.BookEditScreen;
14 | import net.minecraft.client.StringSplitter;
15 | import net.minecraft.network.chat.FormattedText;
16 | import net.minecraft.network.chat.Style;
17 |
18 | public class BookEditScreenWrapper extends IMEReceiver {
19 | private IMEOperator myIME;
20 | private BookEditScreen owner;
21 |
22 | public BookEditScreenWrapper(BookEditScreen field) {
23 | ModLogger.log("BookEditScreen init: " + field.hashCode());
24 | owner = field;
25 | myIME = CocoaInput.getController().generateIMEOperator(this);
26 | myIME.setFocused(true);
27 | }
28 |
29 | protected void setText(String text) {
30 | if(owner.isSigning) {
31 | owner.title=text;
32 | }
33 | else {
34 | owner.setCurrentPageText(text);
35 | }
36 | }
37 |
38 | protected String getText() {
39 | if(owner.isSigning) {
40 | return owner.title;
41 | }
42 | else {
43 | return owner.getCurrentPageText();
44 | }
45 | }
46 |
47 | protected void setCursorInvisible() {
48 | owner.frameTick=6;
49 | } //TODO
50 |
51 | protected int getCursorPos() {
52 | if(owner.isSigning) {
53 | return owner.titleEdit.getCursorPos();
54 | }
55 | else {
56 | return owner.pageEdit.getCursorPos();
57 | }
58 | }
59 |
60 | protected void setCursorPos(int p) {
61 | if(owner.isSigning) {
62 | owner.titleEdit.setCursorPos(p,true);
63 | }
64 | else {
65 | owner.pageEdit.setCursorPos(p,true);
66 | }
67 | }
68 |
69 | protected void setSelectionPos(int p) {
70 | if(owner.isSigning) {
71 | owner.titleEdit.setSelectionRange(p, p);
72 | }
73 | else {
74 | owner.pageEdit.setSelectionRange(p, p);
75 | }
76 | }
77 |
78 |
79 | @Override
80 | public Rect getRect() {
81 | Font fontRendererObj = null;
82 | try {
83 | fontRendererObj = WrapperUtil.makeFont(owner);
84 | } catch (Exception e) {
85 | e.printStackTrace();
86 | }
87 | if (owner.isSigning) {
88 | return new Rect(
89 | (fontRendererObj.width(owner.title.substring(0, originalCursorPosition)) / 2 + ((owner.width - 192) / 2) + 36 + (116 - 0) / 2),
90 | (50 + fontRendererObj.lineHeight),
91 | 0,
92 | 0
93 | );
94 | } else {
95 | StringSplitter manager = fontRendererObj.getSplitter();
96 | List lines = manager.splitLines(owner.getCurrentPageText(), 116, Style.EMPTY);
97 | final String[] lastLine = new String[1];
98 | FormattedText.ContentConsumer acceptor = new FormattedText.ContentConsumer() {
99 | @Override
100 | public Optional accept(String p_accept_1_) {
101 | lastLine[0] = p_accept_1_;
102 | return Optional.empty();
103 | }
104 | };
105 | lines.get(lines.size() - 1).visit(acceptor);
106 | return new Rect(
107 | (((owner.width - 192) / 2) + 36 + fontRendererObj.width(lastLine[0])),
108 | (34 + lines.size() * fontRendererObj.lineHeight),
109 | 0,
110 | 0
111 | );
112 | }
113 | }
114 |
115 | public int renewCursorCounter() {
116 | return owner.frameTick+(cursorVisible?1:0);
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/arch/x11/X11Controller.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.arch.x11;
2 |
3 | import java.io.IOException;
4 | import java.lang.reflect.Field;
5 |
6 | import org.lwjgl.glfw.GLFW;
7 | import org.lwjgl.glfw.GLFWNativeX11;
8 |
9 | import com.sun.jna.Memory;
10 | import com.sun.jna.Pointer;
11 | import com.sun.jna.WString;
12 |
13 | import jp.axer.cocoainput.CocoaInput;
14 | import jp.axer.cocoainput.plugin.CocoaInputController;
15 | import jp.axer.cocoainput.plugin.IMEOperator;
16 | import jp.axer.cocoainput.plugin.IMEReceiver;
17 | import net.minecraft.client.Minecraft;
18 | import net.minecraft.client.gui.screens.Screen;
19 |
20 | public class X11Controller implements CocoaInputController {
21 |
22 | static X11IMEOperator focusedOperator = null;
23 |
24 | Handle.DrawCallback c_draw = new Handle.DrawCallback() {
25 | public Pointer invoke(int caret, int chg_first, int chg_length, short length, boolean iswstring,
26 | String rawstring, WString rawwstring, int primary, int secondary, int tertiary) {
27 | Logger.log("Javaside draw begin");
28 | String string = iswstring ? rawwstring.toString() : rawstring;
29 |
30 | if (X11Controller.focusedOperator != null) {
31 | GLFW.glfwSetKeyCallback(window, null);
32 | X11Controller.focusedOperator.owner.setMarkedText(string, caret, tertiary - secondary, 0, 0);
33 | }
34 | Logger.log("Preedit:" + caret + " " + chg_first + " " + chg_length + " " + length + " " + primary + " "
35 | + secondary + " " + tertiary + " " + string);
36 | int[] point = { 600, 600 };
37 | Memory memory = new Memory(8L);
38 | memory.write(0L, point, 0, 2);
39 | Logger.log("Javaside draw end");
40 | return (Pointer) memory;
41 | }
42 | };
43 |
44 | Handle.DoneCallback c_done = new Handle.DoneCallback() {
45 | public void invoke() {
46 | Logger.log("javaside preedit done");
47 | if (X11Controller.focusedOperator != null) {
48 | X11Controller.focusedOperator.owner.insertText("", 0, 0);
49 | }
50 | setupKeyboardEvent();
51 | }
52 | };
53 |
54 | public static void setupKeyboardEvent() {
55 | Minecraft.getInstance().keyboardHandler.setup(window);
56 | GLFW.glfwSetCharModsCallback(window, (p_228000_1_, p_228000_3_, p_228000_4_) -> {
57 | Minecraft.getInstance().execute(() -> {
58 | if (X11Controller.focusedOperator != null) {
59 |
60 | X11Controller.focusedOperator.owner.insertText(String.valueOf(Character.toChars(p_228000_3_)), 0,
61 | 0);
62 |
63 | } else {
64 | Minecraft.getInstance().keyboardHandler.charTyped(p_228000_1_, p_228000_3_, p_228000_4_);
65 | }
66 | });
67 | });
68 | }
69 |
70 | private static final long window = Minecraft.getInstance().getWindow().getWindow();
71 |
72 | public X11Controller() throws IOException {
73 |
74 | setupKeyboardEvent();
75 |
76 | Logger.log("This is X11 Controller");
77 | CocoaInput.copyLibrary("libx11cocoainput.so", "x11/libx11cocoainput.so");
78 | Logger.log("Call clang initializer");
79 | Handle.INSTANCE.initialize(window, GLFWNativeX11.glfwGetX11Window(window), this.c_draw, this.c_done,
80 | Logger.clangLog, Logger.clangError, Logger.clangDebug);
81 | Handle.INSTANCE.set_focus(0);
82 | Logger.log("Finished clang initializer");
83 | Logger.log("X11Controller finished initialize");
84 |
85 | }
86 |
87 | @Override
88 | public IMEOperator generateIMEOperator(IMEReceiver arg0) {
89 | // TODO Auto-generated method stub
90 | return new X11IMEOperator(arg0);
91 | }
92 |
93 | @Override
94 | public void screenOpenNotify(Screen gui) {
95 | try {
96 | Field wrapper = gui.getClass().getField("wrapper");
97 | wrapper.setAccessible(true);
98 | if (wrapper.get(gui) instanceof IMEReceiver)
99 | return;
100 | } catch (Exception e) {
101 | /* relax */}
102 | if (X11Controller.focusedOperator != null) {
103 | X11Controller.focusedOperator.setFocused(false);
104 | X11Controller.focusedOperator = null;
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/cocoainput.m:
--------------------------------------------------------------------------------
1 | //
2 | // cocoainput.m
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 | #import
9 | #import
10 | #import "cocoainput.h"
11 | #import "DataManager.h"
12 |
13 | void replaceInstanceMethod(Class cls, SEL sel, SEL renamedSel, Class dataCls) {
14 | Method methodReplacedWith = class_getInstanceMethod(cls, sel);
15 | IMP imp = method_getImplementation(methodReplacedWith);
16 | const char* encoding = method_getTypeEncoding(methodReplacedWith);
17 | class_addMethod(cls, renamedSel, imp, encoding);
18 | methodReplacedWith = class_getInstanceMethod(dataCls, sel);
19 | imp = method_getImplementation(methodReplacedWith);
20 | encoding = method_getTypeEncoding(methodReplacedWith);
21 | class_replaceMethod(cls, sel, imp, encoding);
22 | }
23 |
24 | void initialize(LogFunction log,LogFunction error,LogFunction debug){
25 | initLogPointer(log, error, debug);
26 | CILog([NSString stringWithFormat:@"Libcocoainput was built on %s %s.", __DATE__, __TIME__]);
27 | CILog(@"CocoaInput is being initialized.Now running thread for modify GLFWview .");
28 | NSThread *thread=[[NSThread alloc]initWithTarget:[DataManager sharedManager] selector:@selector(modifyGLFWView) object:nil];
29 | [thread start];
30 | }
31 |
32 | void addInstance(const char* uuid,
33 | void (*insertText_p)(const char*, const int, const int),
34 | void (*setMarkedText_p)(const char*,
35 | const int,
36 | const int,
37 | const int,
38 | const int),
39 | float* (*firstRectForCharacterRange_p)(void)) {
40 | CIDebug([NSString stringWithFormat:@"New textfield %s has registered.", uuid]);
41 | MinecraftView* mc = [[MinecraftView alloc] init];
42 | mc.insertText = insertText_p;
43 | mc.setMarkedText = setMarkedText_p;
44 | mc.firstRectForCharacterRange = firstRectForCharacterRange_p;
45 | [[[DataManager sharedManager] dic]
46 | setObject:mc
47 | forKey:[[NSString alloc] initWithCString:uuid
48 | encoding:NSUTF8StringEncoding]];
49 | }
50 |
51 | void removeInstance(const char* uuid) {
52 | CIDebug([NSString stringWithFormat:@"Textfield %s has been removed.", uuid]);
53 | [[[DataManager sharedManager] dic]
54 | removeObjectForKey:[[NSString alloc]
55 | initWithCString:uuid
56 | encoding:NSUTF8StringEncoding]];
57 | }
58 |
59 | void refreshInstance(void) {
60 | CIDebug(@"All textfields has been removed.");
61 | [[NSTextInputContext currentInputContext] discardMarkedText];
62 | [DataManager sharedManager].activeView = nil;
63 | [DataManager sharedManager].dic = [NSMutableDictionary dictionary];
64 | }
65 |
66 | void discardMarkedText(const char* uuid) {
67 | CIDebug(@"Active marked text has been discarded.");
68 | }
69 |
70 | void setIfReceiveEvent(const char* uuid, int yn) {
71 | CIDebug([NSString stringWithFormat:@"Textfield %s's flag has changed to %d.",
72 | uuid, yn]);
73 | if (yn == 1) {
74 | [DataManager sharedManager].activeView = [[[DataManager sharedManager] dic]
75 | objectForKey:[[NSString alloc] initWithCString:uuid
76 | encoding:NSUTF8StringEncoding]];
77 | } else {
78 | if ([DataManager sharedManager].activeView != nil &&
79 | [[[[DataManager sharedManager] dic]
80 | objectForKey:[[NSString alloc]
81 | initWithCString:uuid
82 | encoding:NSUTF8StringEncoding]]
83 | isEqual:[DataManager sharedManager].activeView])
84 | [DataManager sharedManager].activeView = nil;
85 | }
86 | }
87 |
88 | float invertYCoordinate(float y) {
89 | CIDebug(@"InvertYCoordinate function used");
90 | return [[NSScreen mainScreen] visibleFrame].size.height +
91 | [[NSScreen mainScreen] visibleFrame].origin.y - y;
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/plugin/IMEReceiver.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.plugin;
2 |
3 | import jp.axer.cocoainput.CocoaInput;
4 | import jp.axer.cocoainput.arch.win.Logger;
5 | import jp.axer.cocoainput.util.PreeditFormatter;
6 | import jp.axer.cocoainput.util.Rect;
7 | import jp.axer.cocoainput.util.Tuple3;
8 | import net.minecraft.client.Minecraft;
9 |
10 | public abstract class IMEReceiver {
11 |
12 | private int length = 0;
13 | protected boolean cursorVisible = true;
14 | private boolean preeditBegin = false;
15 | protected int originalCursorPosition = 0;
16 |
17 | /*
18 | * position1 length1は下線と強調変換のため必須 position2 length2は意味をなしてない
19 | * positionの位置から文字数lengthの範囲という意味
20 | */
21 | public void insertText(String aString, int position1, int length1) {//確定文字列 現状aString以外の引数は意味をなしてない
22 | if (true) {
23 | Logger.log("just comming:(" + aString + ") now:(" + getText() + ")");
24 | }
25 | if (!preeditBegin) {
26 | originalCursorPosition = this.getCursorPos();
27 | }
28 | preeditBegin = false;
29 | cursorVisible = true;
30 | this.setText((new StringBuffer(this.getText()))
31 | .replace(originalCursorPosition, originalCursorPosition + length, "").toString());
32 | length = 0;
33 | this.setCursorPos(originalCursorPosition);
34 | this.setSelectionPos(originalCursorPosition);
35 | if (CocoaInput.config.isNativeCharTyped()) {
36 | this.insertTextNative(aString);
37 | } else {
38 | this.insertTextEmurated(aString);
39 | }
40 | /*
41 | if (aString.length() == 0) {
42 | this.setText((new StringBuffer(this.getText()))
43 | .replace(originalCursorPosition, originalCursorPosition + length, "").toString());
44 | length = 0;
45 | this.setCursorPos(originalCursorPosition);
46 | this.setSelectionPos(originalCursorPosition);
47 | return;
48 | }
49 | this.setText((new StringBuffer(this.getText()))
50 | .replace(originalCursorPosition, originalCursorPosition + length,
51 | aString.substring(0, aString.length()))
52 | .toString());
53 | length = 0;
54 | this.setCursorPos(originalCursorPosition + aString.length());
55 | this.notifyParent(this.getText());
56 | //owner.selectionEnd = owner.cursorPosition;
57 | */
58 | }
59 |
60 | public void setMarkedText(String aString, int position1, int length1, int position2, int length2) {
61 | if (!preeditBegin) {
62 | originalCursorPosition = this.getCursorPos();
63 | preeditBegin = true;
64 | }
65 | int caretPosition;
66 | boolean hasCaret;
67 | String commitString;
68 | if (CocoaInput.config.isAdvancedPreeditDraw()) {
69 | Tuple3 formattedText = PreeditFormatter.formatMarkedText(aString, position1,
70 | length1);
71 | commitString = formattedText._1();
72 | caretPosition = formattedText._2() + 4;//相対値
73 | hasCaret = formattedText._3();
74 |
75 | }
76 | else {
77 | hasCaret=true;
78 | caretPosition=0;
79 | commitString=PreeditFormatter.SECTION+"n"+aString+PreeditFormatter.SECTION+"r";
80 | }
81 | this.setText((new StringBuffer(this.getText()))
82 | .replace(originalCursorPosition, originalCursorPosition + length, commitString).toString());
83 | length = commitString.length();
84 | if (hasCaret) {
85 | this.cursorVisible = true;
86 | this.setCursorPos(originalCursorPosition + caretPosition);
87 | this.setSelectionPos(originalCursorPosition + caretPosition);
88 | } else {
89 | this.cursorVisible = false;
90 | this.setCursorInvisible();
91 | this.setCursorPos(originalCursorPosition);
92 | this.setSelectionPos(originalCursorPosition);
93 | //owner.selectionEnd=owner.cursorPosition;
94 | }
95 | }
96 |
97 | public abstract Rect getRect();
98 |
99 | abstract protected void setText(String text);
100 |
101 | abstract protected String getText();
102 |
103 | abstract protected void setCursorInvisible();
104 |
105 | abstract protected int getCursorPos();
106 |
107 | abstract protected void setCursorPos(int p);
108 |
109 | abstract protected void setSelectionPos(int p);
110 |
111 | protected void insertTextNative(String text) {
112 | for (char c : text.toCharArray()) {
113 | Minecraft instance = Minecraft.getInstance();
114 | instance.keyboardHandler.charTyped(instance.getWindow().getWindow(), c, 0);
115 | }
116 | }
117 |
118 | protected void insertTextEmurated(String aString) {
119 | this.setText((new StringBuffer(this.getText()))
120 | .replace(this.getCursorPos(), this.getCursorPos(),
121 | aString.substring(0, aString.length()))
122 | .toString());
123 | length = 0;
124 | this.setCursorPos(this.getCursorPos() + aString.length());
125 | this.notifyParent(this.getText());
126 | }
127 |
128 | protected void notifyParent(String text) {
129 | };
130 | }
131 |
--------------------------------------------------------------------------------
/libcocoainput/win/libwincocoainput.c:
--------------------------------------------------------------------------------
1 | #include "libwincocoainput.h"
2 | #include
3 |
4 | void (*javaDone)(wchar_t*);
5 | int* (*javaDraw)(wchar_t*,int,int);
6 | int (*javaRect)(float*);
7 |
8 |
9 |
10 | void setCallback(int*(*c_draw)(wchar_t*,int,int),void(*c_done)(wchar_t*),int (*c_rect)(float*)){
11 | javaDraw=c_draw;
12 | javaDone=c_done;
13 | javaRect=c_rect;
14 | }
15 |
16 |
17 | HWND hwnd;
18 | HIMC himc;
19 |
20 |
21 | LRESULT compositionLocationNotify(HWND hWnd){
22 | HIMC imc=NULL;
23 | float *rect= malloc(sizeof(float)*4);
24 | CILog("ready call javaRect");
25 | if(javaRect(rect)){
26 | free(rect);
27 | return FALSE;
28 | }
29 | CANDIDATEFORM rectStruct = {0,CFS_EXCLUDE,{rect[0],rect[1]},{rect[0]-rect[2],rect[1]-rect[3],rect[0]+1,rect[1]+1}};
30 | imc=ImmGetContext(hwnd);
31 | ImmSetCandidateWindow(imc,&rectStruct);
32 | ImmReleaseContext(hWnd,imc);
33 | free(rect);
34 | return TRUE;
35 | }
36 |
37 | LRESULT CALLBACK (*glfwWndProc)(HWND,UINT,WPARAM,LPARAM);
38 | LRESULT CALLBACK wrapper_wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
39 | switch(msg){
40 | case WM_IME_NOTIFY:{
41 | if(wParam==IMN_OPENCANDIDATE){
42 | compositionLocationNotify(hWnd);
43 | return TRUE;
44 | }
45 | else{
46 | break;
47 | }
48 | }
49 | case WM_IME_STARTCOMPOSITION:{
50 | compositionLocationNotify(hWnd);
51 | return TRUE;
52 | }
53 | case WM_IME_ENDCOMPOSITION:{
54 | javaDone(L"");
55 | return TRUE;
56 | }
57 | case WM_IME_COMPOSITION:{
58 | HIMC imc=NULL;
59 | LONG textSize,attrSize,clauseSize;
60 | int i, focusedBlock, length;
61 | LPWSTR buffer;
62 | LPSTR attributes;
63 | DWORD* clauses;
64 | LONG cursor=0;
65 | if(lParam&GCS_RESULTSTR){
66 | CILog("ResultStr");
67 | imc=ImmGetContext(hwnd);
68 | textSize = ImmGetCompositionStringW(imc, GCS_RESULTSTR, NULL, 0);
69 | length = textSize / sizeof(WCHAR);
70 | buffer = calloc(length + 1, sizeof(WCHAR));
71 | ImmGetCompositionStringW(imc, GCS_RESULTSTR, buffer, textSize);
72 | ImmReleaseContext(hWnd, imc);
73 | javaDone(buffer);
74 | }
75 | if(lParam&GCS_COMPSTR){
76 | imc=ImmGetContext(hwnd);
77 | if(lParam&GCS_CURSORPOS){
78 | cursor=ImmGetCompositionStringW(imc, GCS_CURSORPOS, NULL, 0);
79 | }
80 |
81 | textSize = ImmGetCompositionStringW(imc, GCS_COMPSTR, NULL, 0);
82 | attrSize = ImmGetCompositionStringW(imc, GCS_COMPATTR, NULL, 0);
83 | clauseSize = ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, NULL, 0);
84 | if(textSize<=0){
85 | ImmReleaseContext(hWnd, imc);
86 | javaDone(L"");
87 | }
88 | else{
89 | length = textSize / sizeof(WCHAR);
90 | buffer = calloc(length + 1, sizeof(WCHAR));
91 | attributes = calloc(attrSize, 1);
92 | clauses = calloc(clauseSize, 1);
93 | ImmGetCompositionStringW(imc, GCS_COMPSTR, buffer, textSize);
94 | ImmGetCompositionStringW(imc, GCS_COMPATTR, attributes, attrSize);
95 | ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, clauses, clauseSize);
96 | ImmReleaseContext(hWnd, imc);
97 | int selected_begin=-1;
98 | int selected_length=0;
99 | int i;
100 | for(i=0;i=0){
109 | cursor=selected_begin;
110 | }
111 | compositionLocationNotify(hWnd);
112 | javaDraw(buffer,cursor,selected_length);
113 | }
114 | }
115 | return TRUE;
116 | }
117 | default:break;
118 | }
119 | return CallWindowProc(glfwWndProc,hWnd,msg,wParam,lParam);
120 | }
121 |
122 |
123 |
124 | void initialize(
125 | long hwndp,
126 | int*(*c_draw)(wchar_t*,int,int),
127 | void(*c_done)(wchar_t*),
128 | int (*c_rect)(float*),
129 | LogFunction log,
130 | LogFunction error,
131 | LogFunction debug
132 | ){
133 | initLogPointer(log,error,debug);
134 | CILog("CocoaInput Windows Clang Initializer start. library compiled at %s %s",__DATE__,__TIME__);
135 | setCallback(c_draw,c_done,c_rect);
136 | hwnd=(HWND)hwndp;
137 | glfwWndProc = GetWindowLongPtr(hwnd,GWLP_WNDPROC);
138 | SetWindowLongPtr(hwnd,GWLP_WNDPROC,wrapper_wndProc);
139 | CILog("Window procedure replaced");
140 | //input_himc = ImmGetContext(hwnd);
141 | /*if(!hImc){
142 | hImc = ImmCreateContext();
143 | HIMC oldhImc = ImmAssociateContext( hwnd, hImc );
144 | }*/
145 | //ImmReleaseContext(hwnd,input_himc);
146 | himc = ImmGetContext(hwnd);
147 | if(!himc){
148 | himc = ImmCreateContext();
149 | }
150 | ImmReleaseContext(hwnd,himc);
151 | himc=ImmAssociateContext(hwnd,0);
152 | CILog("CocoaInput Windows initializer done!");
153 | }
154 |
155 | void set_focus(int flag){
156 |
157 | CILog("setFocused:%d",flag);
158 | if(flag){
159 | ImmAssociateContext(hwnd,himc);
160 | compositionLocationNotify(hwnd);
161 | }
162 | else{
163 | himc=ImmAssociateContext(hwnd,0);
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/libcocoainput/x11/libx11cocoainput.c:
--------------------------------------------------------------------------------
1 | #include "libx11cocoainput.h"
2 |
3 | void (*javaDone)();
4 | int* (*javaDraw)(int,int,int,short,int,char*,wchar_t*,int,int,int);
5 | XICCallback calet,start,done,draw;
6 | XICCallback s_start,s_done,s_draw;
7 |
8 |
9 |
10 |
11 | void setCallback(int*(*c_draw)(int,int,int,short,int,char*,wchar_t*,int,int,int),void(*c_done)()){
12 | javaDraw=c_draw;
13 | javaDone=c_done;
14 | }
15 |
16 |
17 | int preeditCalet(XIC xic,XPointer clientData,XPointer data){
18 | return 0;
19 | }
20 | int preeditStart(XIC xic,XPointer clientData,XPointer data){
21 | CILog("Preedit start");
22 | return 0;
23 | }
24 | int preeditDone(XIC xic,XPointer clientData,XPointer data){
25 | CILog("Preedit end");
26 | javaDone();
27 | return 0;
28 | }
29 | int preeditDraw(XIC xic,XPointer clientData,XPointer structptr){
30 | CILog("Preedit draw start");
31 | XIMPreeditDrawCallbackStruct* structure=(XIMPreeditDrawCallbackStruct*)structptr;
32 | int *array;
33 | int secondary=0;
34 | int length=0;
35 | if(structure->text){
36 | int i=0;
37 | int secondary_determined=0;
38 | for(i=0;i!=structure->text->length;i++){
39 | if(!secondary_determined&&structure->text->feedback[i]!=XIMUnderline){
40 | secondary=i;
41 | secondary_determined=1;
42 | }
43 | if(secondary_determined&&(structure->text->feedback[i]==0||structure->text->feedback[i]!=XIMUnderline)){
44 | length++;
45 | }
46 | else if(secondary_determined)break;
47 | }
48 | }
49 |
50 | CILog("Invoke Javaside");
51 | if(structure->text){
52 | array=javaDraw(
53 | structure->caret,
54 | structure->chg_first,
55 | structure->chg_length,
56 | structure->text->length,
57 | structure->text->encoding_is_wchar,
58 | structure->text->encoding_is_wchar?"":structure->text->string.multi_byte,
59 | structure->text->encoding_is_wchar?structure->text->string.wide_char:L"",
60 | 0,
61 | secondary,
62 | secondary+length
63 | );
64 | }
65 | else {
66 | array=javaDraw(
67 | structure->caret,
68 | structure->chg_first,
69 | structure->chg_length,
70 | 0,
71 | 0,
72 | "",
73 | L"",
74 | 0,
75 | 0,
76 | 0
77 | );
78 | }
79 |
80 | //TODO なんとかしてon-the-spotの候補ウィンドウをちゃんとした位置にしたいね(願望)
81 | XVaNestedList attr;
82 | XPoint place;
83 | place.x=array[0];place.y=array[1];
84 | attr=XVaCreateNestedList(0,XNSpotLocation,&place,NULL);
85 | XSetICValues(xic,XNPreeditAttributes,attr,NULL);
86 | XFree(attr);
87 | CILog("Preedit draw end");
88 | return 0;
89 | }
90 |
91 | int statusStart(XIC xic,XPointer clientData,XPointer data){
92 | return 0;
93 | }
94 | int statusDone(XIC xic,XPointer clientData,XPointer data){
95 | return 0;
96 | }
97 | int statusDraw(XIC xic,XPointer clientData,XPointer data/*,XIMStatusDrawCallbackStruct *structure*/){
98 | return 0;
99 | }
100 |
101 |
102 |
103 | XVaNestedList preeditCallbacksList(){
104 | calet.client_data=NULL;
105 | start.client_data=NULL;
106 | done.client_data=NULL;
107 | draw.client_data=NULL;
108 | calet.callback=preeditCalet;
109 | start.callback=preeditStart;
110 | done.callback=preeditDone;
111 | draw.callback=preeditDraw;
112 | return XVaCreateNestedList(0,
113 | XNPreeditStartCallback,
114 | &start,
115 | XNPreeditCaretCallback,
116 | &calet,
117 | XNPreeditDoneCallback,
118 | &done,
119 | XNPreeditDrawCallback,
120 | &draw,NULL);
121 | }
122 |
123 |
124 | XVaNestedList statusCallbacksList(){
125 | s_start.client_data=NULL;
126 | s_done.client_data=NULL;
127 | s_draw.client_data=NULL;
128 | s_start.callback=statusStart;
129 | s_done.callback=statusDone;
130 | s_draw.callback=statusDraw;
131 | return XVaCreateNestedList(0,
132 | XNStatusStartCallback,
133 | &s_start,
134 | XNStatusDoneCallback,
135 | &s_done,
136 | XNStatusDrawCallback,
137 | &s_draw,NULL);
138 | }
139 |
140 |
141 |
142 | _GLFWwindowX11 * x11c; //_GLFWwindowX11のアドレス
143 | XIM xim; //_GLFWwindowX11が保持するXIM
144 | Window xwindow; //
145 |
146 |
147 | XIC activeic; // IMが有効なIC
148 | XIC inactiveic; //IMが無効なIC
149 |
150 |
151 |
152 | void initialize(
153 | long waddr,
154 | long xw,
155 | int*(*c_draw)(int,int,int,short,int,char*,wchar_t*,int,int,int),
156 | void(*c_done)(),
157 | LogFunction log,
158 | LogFunction error,
159 | LogFunction debug
160 | ){
161 | initLogPointer(log,error,debug);
162 | CILog("CocoaInput X11 Clang Initializer start. library compiled at %s %s",__DATE__,__TIME__);
163 |
164 | setCallback(c_draw,c_done);
165 |
166 | CILog("Window ptr:%p",(Window)xw);
167 | CILog("GLFWwindow ptr:%p",(void*)waddr);
168 | CILog("Searching _GLFWwindowx11 from GLFWwindow ptr...");
169 | int i;
170 | XIC ic=NULL;
171 | for(i=0;i<0x500;i++){
172 | Window po = (*(((_GLFWwindowX11*)(waddr+i)))).handle;
173 | if(po!=xw)continue;
174 | x11c = (((_GLFWwindowX11*)(waddr+i)));
175 | ic = (*(((_GLFWwindowX11*)(waddr+i)))).ic;
176 | CILog("Found offset:%d ,_GLFWwindowX11(%p)=GLFWwindow(%p)+%d ",i,x11c,(void*)waddr,i);
177 | break;
178 | }
179 | CILog("XIC mem address:%p",x11c->ic);
180 | xim = XIMOfIC(ic);
181 | CILog("XIM mem address:%p",xim);
182 | xwindow=xw;
183 | inactiveic = XCreateIC(
184 | xim,
185 | XNClientWindow,
186 | (Window)xwindow,
187 | XNFocusWindow,
188 | (Window)xwindow,
189 | XNInputStyle,
190 | XIMPreeditNone|XIMStatusNone,
191 | NULL);
192 | CILog("Created inactiveic-> default");
193 | activeic = XCreateIC(
194 | xim,
195 | XNClientWindow,
196 | xwindow,
197 | XNFocusWindow,
198 | xwindow,
199 | XNInputStyle,
200 | XIMPreeditCallbacks|XIMStatusNone,
201 | //XIMPreeditNothing|XIMStatusNothing,
202 | XNPreeditAttributes,
203 | preeditCallbacksList(),
204 | XNStatusAttributes,
205 | statusCallbacksList(),
206 | NULL);
207 | CILog("Created activeic");
208 | XSetICFocus(inactiveic);
209 | XUnsetICFocus(activeic);
210 | CILog("Completed ic focus");
211 | XDestroyIC(x11c->ic);
212 | x11c->ic = inactiveic;
213 | CILog("Destroyed glfw ic");
214 | CILog("CocoaInput X11 initializer done!");
215 | }
216 |
217 | void set_focus(int flag){
218 | XUnsetICFocus(x11c->ic);
219 | if(flag){
220 | x11c->ic=activeic;
221 | }
222 | else{
223 | x11c->ic= inactiveic;
224 | }
225 | XSetICFocus(x11c->ic);
226 | CILog("setFocused:%d",flag);
227 | }
228 |
--------------------------------------------------------------------------------
/fabric/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/forge/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/forge/build.gradle:
--------------------------------------------------------------------------------
1 | import org.codehaus.plexus.util.Os
2 |
3 | buildscript {
4 | repositories {
5 | maven { url = 'https://files.minecraftforge.net/maven' }
6 | jcenter()
7 | mavenCentral()
8 | maven { url='https://repo.spongepowered.org/maven' }
9 | }
10 | dependencies {
11 | classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
12 | classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
13 | }
14 | }
15 | apply plugin: 'net.minecraftforge.gradle'
16 | // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
17 | apply plugin: 'eclipse'
18 | apply plugin: 'maven-publish'
19 | apply plugin: 'org.spongepowered.mixin'
20 |
21 | version = '4.0.4'
22 | group = 'jp.axer.cocoainput' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
23 | archivesBaseName = 'CocoaInput-1.18-forge'
24 |
25 | // Mojang ships Java 16 to end users in 1.17+ instead of Java 8 in 1.16 or lower, so your mod should target Java 16.
26 | java.toolchain.languageVersion = JavaLanguageVersion.of(17)
27 |
28 | println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
29 | minecraft {
30 | // The mappings can be changed at any time, and must be in the following format.
31 | // snapshot_YYYYMMDD Snapshot are built nightly.
32 | // stable_# Stables are built at the discretion of the MCP team.
33 | // Use non-default mappings at your own risk. they may not always work.
34 | // Simply re-run your setup task after changing the mappings to update your workspace.
35 | mappings channel: 'official', version: '1.18'
36 | // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
37 |
38 | // accessTransformer = file('build/resources/main/META-INF/accesstransformer.cfg')
39 | accessTransformer = file('../src/forge/resources/META-INF/accesstransformer.cfg')
40 |
41 | // Default run configurations.
42 | // These can be tweaked, removed, or duplicated as needed.
43 | runs {
44 | client {
45 | workingDirectory project.file('run')
46 |
47 | // Recommended logging data for a userdev environment
48 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
49 |
50 | // Recommended logging level for the console
51 | property 'forge.logging.console.level', 'debug'
52 | arg "-mixin.config=cocoainput.mixins.json"
53 |
54 | sourceSets.main.java.srcDirs+=['../src/forge/java']
55 | sourceSets.main.java.srcDirs+=['../src/main/java']
56 | sourceSets.main.resources.srcDirs+=['../src/forge/resources']
57 | sourceSets.main.resources.srcDirs+=['../src/main/resources']
58 | mods {
59 | examplemod {
60 | source sourceSets.main
61 | }
62 | }
63 | }
64 |
65 | server {
66 | workingDirectory project.file('run')
67 |
68 | // Recommended logging data for a userdev environment
69 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
70 |
71 | // Recommended logging level for the console
72 | property 'forge.logging.console.level', 'debug'
73 |
74 | mods {
75 | examplemod {
76 | source sourceSets.main
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
83 | mixin {
84 | add sourceSets.main, "cocoainput.refmap.json"
85 | }
86 |
87 | dependencies {
88 | // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
89 | // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
90 | // The userdev artifact is a special name and will get all sorts of transformations applied to it.
91 | minecraft 'net.minecraftforge:forge:1.18-38.0.15'
92 |
93 | // You may put jars on which you depend on in ./libs or you may define them like so..
94 | // compile "some.group:artifact:version:classifier"
95 | // compile "some.group:artifact:version"
96 |
97 | // Real examples
98 | // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
99 | // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
100 |
101 | // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
102 | // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
103 |
104 | // These dependencies get remapped to your current MCP mappings
105 | // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
106 |
107 | // For more info...
108 | // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
109 | // http://www.gradle.org/docs/current/userguide/dependency_management.html
110 | annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
111 |
112 | }
113 |
114 |
115 | // Example for how to get properties into the manifest for reading by the runtime..
116 | jar {
117 | manifest {
118 | attributes([
119 | "Specification-Title": "CocoaInput",
120 | "Specification-Vendor": "Axeryok",
121 | "Specification-Version": "1", // We are version 1 of ourselves
122 | "Implementation-Title": project.name,
123 | "Implementation-Version": "${version}",
124 | "Implementation-Vendor" :"Axeryok",
125 | "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
126 | "MixinConfigs":"cocoainput.mixins.json"
127 | ])
128 | }
129 | }
130 |
131 | // Example configuration to allow publishing using the maven-publish task
132 | // This is the preferred method to reobfuscate your jar file
133 | jar.finalizedBy('reobfJar')
134 | // However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
135 | //publish.dependsOn('reobfJar')
136 |
137 | publishing {
138 | publications {
139 | mavenJava(MavenPublication) {
140 | artifact jar
141 | }
142 | }
143 | repositories {
144 | maven {
145 | url "file:///${project.projectDir}/mcmodsrepo"
146 | }
147 | }
148 | }
149 |
150 |
--------------------------------------------------------------------------------
/libcocoainput/darwin/libcocoainput/DataManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // DataManager.m
3 | // libcocoainput
4 | //
5 | // Created by Axer on 2019/03/23.
6 | // Copyright © 2019年 Axer. All rights reserved.
7 | //
8 |
9 | #import "DataManager.h"
10 | #import "cocoainput.h"
11 | #import "Logger.h"
12 |
13 | #define SPLIT_NSRANGE(x) (int)(x.location), (int)(x.length)
14 |
15 | static DataManager* instance = nil;
16 |
17 | @implementation DataManager
18 |
19 | @synthesize hasPreeditText;
20 | @synthesize isSentedInsertText;
21 | @synthesize isBeforeActionSetMarkedText;
22 |
23 | + (instancetype)sharedManager {
24 | if (!instance) {
25 | instance = [[DataManager alloc] init];
26 | }
27 | return instance;
28 | }
29 |
30 | - (id)init {
31 | CIDebug(@"Textfield table has been initialized.");
32 | self = [super init];
33 | self.hasPreeditText=NO;
34 | self.dic = [NSMutableDictionary dictionary];
35 | self.activeView = nil;
36 | return self;
37 | }
38 |
39 | - (void) modifyGLFWView{
40 | NSView *view;
41 | while(1){
42 | view=[[NSApp keyWindow] contentView];
43 | if([[view className]isEqualToString:@"GLFWContentView"]==YES)break;
44 | }
45 | [[DataManager sharedManager] setGlfwView:view];
46 | replaceInstanceMethod([view class], @selector(keyDown:), @selector(org_keyDown:), [[DataManager sharedManager] class]);
47 | replaceInstanceMethod([view class], @selector(hasMarkedText), @selector(org_hasMarkedText), [[DataManager sharedManager] class]);
48 | replaceInstanceMethod([view class], @selector(markedRange), @selector(org_markedRange), [[DataManager sharedManager] class]);
49 | replaceInstanceMethod([view class], @selector(interpretKeyEvents:), @selector(org_interpretKeyEvents:), [[DataManager sharedManager] class]);
50 | replaceInstanceMethod([view class], @selector(insertText:replacementRange:), @selector(org_insertText:replacementRange:), [[DataManager sharedManager] class]);
51 | replaceInstanceMethod([view class],@selector(firstRectForCharacterRange:actualRange:),@selector(org_firstRectForCharacterRange:actualRange:),[[DataManager sharedManager] class]);
52 | replaceInstanceMethod([view class], @selector(setMarkedText:selectedRange:replacementRange:), @selector(org_setMarkedText:selectedRange:replacementRange:), [[DataManager sharedManager] class]);
53 | replaceInstanceMethod([view class], @selector(unmarkText), @selector(org_unmarkText), [[DataManager sharedManager] class]);
54 | CILog(@"Complete to modify GLFWView");
55 | }
56 |
57 | - (void)keyDown:(NSEvent*)theEvent {//GLFWContentView改変用
58 | //見づらすぎて改修しづらい
59 | if ([DataManager sharedManager].activeView != nil ){
60 | CIDebug(@"New keyEvent came and sent to textfield.");
61 | [self org_interpretKeyEvents:@[ theEvent ]];
62 | }
63 | //NSLog(@"keydown %d %d %d\n",[DataManager sharedManager].hasPreeditText,[DataManager sharedManager].isSentedInsertText,[DataManager sharedManager].isBeforeActionSetMarkedText);
64 | if ([DataManager sharedManager].hasPreeditText==NO&&[DataManager sharedManager].isSentedInsertText==NO&&[DataManager sharedManager].isBeforeActionSetMarkedText==NO){
65 | CIDebug(@"New keyEvent came and sent to original keyDown.");
66 | [self org_keyDown:theEvent];
67 | }
68 | [DataManager sharedManager].isSentedInsertText = NO;
69 | [DataManager sharedManager].isBeforeActionSetMarkedText = NO;
70 | }
71 |
72 | - (void)interpretKeyEvents:(NSArray*)eventArray{//GLFWContentView改変用
73 | ;
74 | }
75 |
76 | - (void)unmarkText {
77 | [DataManager sharedManager].isBeforeActionSetMarkedText = YES;
78 | [DataManager sharedManager].hasPreeditText = NO;
79 | [self org_unmarkText];
80 | }
81 |
82 | //確定文字列 (漢字変換を通さなかったものもここに入る)
83 | - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
84 | if (![DataManager sharedManager].hasPreeditText) {
85 | [DataManager sharedManager].isSentedInsertText = NO;
86 | [self org_insertText:aString replacementRange:replacementRange];
87 | return;
88 | }
89 | [DataManager sharedManager].hasPreeditText = NO;
90 | [DataManager sharedManager].isSentedInsertText = YES;
91 | /*const char *sentString;
92 | if ([aString isKindOfClass:[NSAttributedString class]]) {
93 | sentString = [[aString string] cStringUsingEncoding:NSUTF8StringEncoding];
94 | }
95 | else{
96 | sentString = [aString cStringUsingEncoding:NSUTF8StringEncoding];
97 | }*/
98 | [[DataManager sharedManager] activeView].insertText("",0,0);
99 | CIDebug([NSString stringWithFormat:@"MarkedText was determined:\"%@\"",aString]);
100 | [self org_insertText:aString replacementRange:replacementRange];//GLFWのオリジナルメソッドはCharEventを発行するので利用する
101 | }
102 |
103 | //漢字変換途中経過
104 | - (void)setMarkedText:(id)aString
105 | selectedRange:(NSRange)selectedRange
106 | replacementRange:(NSRange)replacementRange {
107 | [DataManager sharedManager].hasPreeditText = YES;
108 | NSString* debugText = aString;
109 | const char* sentString;
110 | if ([aString isKindOfClass:[NSAttributedString class]]) {
111 | sentString = [[aString string] cStringUsingEncoding:NSUTF8StringEncoding];
112 | debugText = [aString string];
113 | } else {
114 | sentString = [aString cStringUsingEncoding:NSUTF8StringEncoding];
115 | }
116 | CIDebug([NSString stringWithFormat:@"MarkedText changed:\"%@\"", [aString description]]);
117 | [[DataManager sharedManager] activeView].setMarkedText(sentString, SPLIT_NSRANGE(selectedRange),
118 | SPLIT_NSRANGE(replacementRange));
119 | [self org_setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
120 | }
121 |
122 | - (NSRect)firstRectForCharacterRange:(NSRange)aRange
123 | actualRange:(NSRangePointer)actualRange {
124 | CIDebug(@"Called to determine where to draw.");
125 | if ([DataManager sharedManager].hasPreeditText == NO) {
126 | return [self org_firstRectForCharacterRange:aRange actualRange:actualRange];
127 | }
128 | float* rect = [[DataManager sharedManager] activeView].firstRectForCharacterRange();
129 | NSRect lwjgl = [self org_firstRectForCharacterRange:aRange actualRange:actualRange];//GLFWのオリジナルを呼び出すとウィンドウのポジションが得られるので利用する
130 | return NSMakeRect(rect[0]+lwjgl.origin.x,
131 | [[[DataManager sharedManager] glfwView] frame].size.height-rect[1]+lwjgl.origin.y,
132 | rect[2],
133 | rect[3]);
134 | }
135 |
136 | - (BOOL)hasMarkedText {
137 | return NO;
138 | }
139 |
140 | - (NSRange)selectedRange {
141 | return NSMakeRange(NSNotFound, 0);
142 | }
143 |
144 | - (NSRange)markedRange {
145 | [[DataManager sharedManager] activeView].insertText("", 0, 0);
146 | [self unmarkText];
147 | return NSMakeRange(NSNotFound, 0);
148 | }
149 |
150 | - (NSArray*)validAttributesForMarkedText {
151 | return nil;
152 | }
153 |
154 | - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange
155 | actualRange:
156 | (NSRangePointer)actualRange {
157 | return nil;
158 | }
159 |
160 | - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint {
161 | return 0;
162 | }
163 |
164 | - (void)doCommandBySelector:(nonnull SEL)selector {
165 | }
166 |
167 |
168 | // 警告消しのためのダミーメソッド
169 | - (NSRange)org_markedRange{return NSMakeRange(NSNotFound, 0);}
170 | - (BOOL)org_hasMarkedText{return YES;};
171 | - (void)org_keyDown:(NSEvent*)theEvent{}
172 | - (void)org_unmarkText{}
173 | - (void)org_interpretKeyEvents:(NSArray*)eventArray{}
174 | - (NSRect)org_firstRectForCharacterRange:(NSRange)aRange
175 | actualRange:(NSRangePointer)actualRange{return NSMakeRect(0,0,0,0);}
176 | - (void)org_insertText:(id)aString replacementRange:(NSRange)replacementRange{}
177 | - (void)org_setMarkedText:(id)aString
178 | selectedRange:(NSRange)selectedRange
179 | replacementRange:(NSRange)replacementRange {}
180 |
181 |
182 | @end
183 |
--------------------------------------------------------------------------------
/src/main/java/jp/axer/cocoainput/util/TinyConfig.java:
--------------------------------------------------------------------------------
1 | package jp.axer.cocoainput.util;
2 | import java.lang.annotation.ElementType;
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 | import java.lang.annotation.Target;
6 | import java.lang.reflect.Field;
7 | import java.lang.reflect.Method;
8 | import java.lang.reflect.Modifier;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.util.AbstractMap;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.function.BiFunction;
17 | import java.util.function.Function;
18 | import java.util.function.Predicate;
19 | import java.util.regex.Pattern;
20 |
21 | import com.google.gson.Gson;
22 | import com.google.gson.GsonBuilder;
23 | import com.mojang.blaze3d.vertex.PoseStack;
24 |
25 | import net.minecraft.client.gui.screens.Screen;
26 | import net.minecraft.client.gui.components.EditBox;
27 | import net.minecraft.client.gui.components.Button;
28 | import net.minecraft.network.chat.BaseComponent;
29 | import net.minecraft.network.chat.TextComponent;
30 | import net.minecraft.network.chat.TranslatableComponent;
31 |
32 | public class TinyConfig {
33 |
34 | private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)");
35 | private static final Pattern DECIMAL_ONLY = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
36 |
37 | private static final List entries = new ArrayList<>();
38 |
39 | protected static class EntryInfo {
40 | Field field;
41 | Object widget;
42 | int width;
43 | String comment;
44 | Method dynamicTooltip;
45 | Map.Entry error;
46 | Object defaultValue;
47 | Object value;
48 | String tempValue;
49 | boolean inLimits = true;
50 | }
51 |
52 | private static Class configClass;
53 | private static String translationPrefix;
54 | private static Path path;
55 |
56 | private static final Gson gson = new GsonBuilder()
57 | .excludeFieldsWithModifiers(Modifier.TRANSIENT)
58 | .excludeFieldsWithModifiers(Modifier.PRIVATE)
59 | .setPrettyPrinting()
60 | .create();
61 |
62 | public static void init(String modid,Path apath, Class> config) {
63 | translationPrefix = modid + ".tinyconfig.";
64 | configClass = config;
65 | path=apath;
66 |
67 | for (Field field : config.getFields()) {
68 | Entry e;
69 | try { e = field.getAnnotation(Entry.class); }
70 | catch (Exception ignored) { continue; }
71 | if(e==null) {continue;}
72 | Class> type = field.getType();
73 | EntryInfo info = new EntryInfo();
74 | info.width = e.width();
75 | info.field = field;
76 |
77 | if (type == int.class) textField(info, Integer::parseInt, INTEGER_ONLY, e.min(), e.max(), true);
78 | else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(),false);
79 | else if (type == String.class) textField(info, String::length, null, Math.min(e.min(),0), Math.max(e.max(),1),true);
80 | else if (type == boolean.class) {
81 | Function