Skip to content

Commit ac7558d

Browse files
committed
Support ITextStoreACPSink for AbstractSignEditScreenMixin
1 parent c72c898 commit ac7558d

File tree

5 files changed

+99
-35
lines changed

5 files changed

+99
-35
lines changed

src/client/java/tech/tnze/client/ACPSinkRegister.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
import tech.tnze.msctf.windows.win32.ui.textservices.ITextStoreACPSink;
44

55
public interface ACPSinkRegister {
6-
default void tnze$registerACPSink(ITextStoreACPSink sink) {
6+
default void tnze$registerACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
77
throw new UnsupportedOperationException("Not implemented yet.");
88
}
99

10-
default void tnze$unregisterACPSink(ITextStoreACPSink sink) {
10+
default void tnze$unregisterACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
1111
throw new UnsupportedOperationException("Not implemented yet.");
1212
}
1313

src/client/java/tech/tnze/client/EditBoxACP.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,17 @@
22

33
import com.mojang.blaze3d.platform.Window;
44
import net.minecraft.client.gui.components.EditBox;
5-
import tech.tnze.msctf.ComObject;
6-
import tech.tnze.msctf.Guid;
75
import tech.tnze.msctf.windows.win32.foundation.POINT;
86
import tech.tnze.msctf.windows.win32.foundation.RECT;
9-
import tech.tnze.msctf.windows.win32.system.com.IUnknown;
107
import tech.tnze.msctf.windows.win32.ui.textservices.*;
118

12-
import java.lang.foreign.Arena;
13-
import java.lang.foreign.MemoryLayout;
149
import java.lang.foreign.MemorySegment;
15-
import java.lang.invoke.VarHandle;
1610

17-
import static com.sun.jna.platform.win32.WinError.E_NOTIMPL;
1811
import static java.lang.foreign.ValueLayout.*;
1912
import static java.lang.foreign.ValueLayout.JAVA_CHAR;
2013
import static tech.tnze.client.IMEClient.LOGGER;
21-
import static tech.tnze.msctf.ComObject.equalIIDs;
2214
import static tech.tnze.msctf.windows.win32.foundation.Constants.*;
23-
import static tech.tnze.msctf.windows.win32.system.ole.Constants.CONNECT_E_ADVISELIMIT;
24-
import static tech.tnze.msctf.windows.win32.system.ole.Constants.CONNECT_E_NOCONNECTION;
2515
import static tech.tnze.msctf.windows.win32.ui.textservices.Constants.*;
26-
import static tech.tnze.msctf.windows.win32.ui.textservices.TEXT_STORE_LOCK_FLAGS.TS_LF_READ;
27-
import static tech.tnze.msctf.windows.win32.ui.textservices.TEXT_STORE_LOCK_FLAGS.TS_LF_READWRITE;
2816

2917
public class EditBoxACP extends AbstractTextFieldACP implements ITextStoreACP2 {
3018
private final EditBox editBox;
@@ -36,12 +24,12 @@ public EditBoxACP(Window window, EditBox editBox) {
3624

3725
@Override
3826
protected void adviseACPSink(ITextStoreACPSink sink) {
39-
editBox.tnze$registerACPSink(sink);
27+
editBox.tnze$registerACPSink(this, sink);
4028
}
4129

4230
@Override
4331
protected void unadviseACPSink(ITextStoreACPSink sink) {
44-
editBox.tnze$unregisterACPSink(sink);
32+
editBox.tnze$unregisterACPSink(this, sink);
4533
}
4634

4735
@Override

src/client/java/tech/tnze/client/SignEditLineACP.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@ public SignEditLineACP(Window window, AbstractSignEditScreen screen, int line) {
2323
this.screen = screen;
2424
}
2525

26+
public int getLine() {
27+
return line;
28+
}
29+
2630
@Override
2731
protected void adviseACPSink(ITextStoreACPSink sink) {
28-
screen.tnze$registerACPSink(sink);
32+
screen.tnze$registerACPSink(this, sink);
2933
}
3034

3135
@Override
3236
protected void unadviseACPSink(ITextStoreACPSink sink) {
33-
screen.tnze$unregisterACPSink(sink);
37+
screen.tnze$unregisterACPSink(this, sink);
3438
}
3539

3640
@Override
@@ -61,18 +65,17 @@ public int GetSelection(int ulIndex, int ulCount, MemorySegment pSelection, Memo
6165
return 0;
6266
}
6367

64-
if (screen.line != line || screen.signField == null) {
65-
pcFetched.set(JAVA_INT, 0, 0);
66-
return 0;
67-
}
68-
6968
if (ulCount < 1) {
7069
LOGGER.error("pSelection too small: {}", ulCount);
7170
return E_FAIL;
7271
}
7372

74-
int cursorPos = screen.signField.getCursorPos();
75-
int selectionPos = screen.signField.getSelectionPos();
73+
int cursorPos = 0, selectionPos = 0;
74+
if (screen.signField != null) {
75+
cursorPos = screen.signField.getCursorPos();
76+
selectionPos = screen.signField.getSelectionPos();
77+
}
78+
7679
TS_SELECTION_ACP.acpStart(pSelection, Math.min(cursorPos, selectionPos));
7780
TS_SELECTION_ACP.acpEnd(pSelection, Math.max(cursorPos, selectionPos));
7881
TS_SELECTION_ACP$style$ase$VH.set(pSelection, 0, cursorPos > selectionPos ? TsActiveSelEnd.TS_AE_END : TsActiveSelEnd.TS_AE_START);

src/client/java/tech/tnze/mixin/client/AbstractSignEditScreenMixin.java

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,121 @@
11
package tech.tnze.mixin.client;
22

3+
import net.minecraft.client.gui.font.TextFieldHelper;
34
import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
45
import net.minecraft.client.input.KeyEvent;
56
import org.jspecify.annotations.Nullable;
7+
import org.spongepowered.asm.mixin.Final;
68
import org.spongepowered.asm.mixin.Mixin;
79
import org.spongepowered.asm.mixin.Shadow;
810
import org.spongepowered.asm.mixin.Unique;
911
import org.spongepowered.asm.mixin.injection.At;
1012
import org.spongepowered.asm.mixin.injection.Inject;
13+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
1114
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1215
import tech.tnze.client.ACPSinkRegister;
16+
import tech.tnze.client.AbstractTextFieldACP;
1317
import tech.tnze.client.Manager;
18+
import tech.tnze.client.SignEditLineACP;
1419
import tech.tnze.msctf.windows.win32.ui.textservices.ITextStoreACPSink;
20+
import tech.tnze.msctf.windows.win32.ui.textservices.TS_TEXTCHANGE;
21+
22+
import java.lang.foreign.Arena;
1523

1624
import static tech.tnze.client.IMEClient.LOGGER;
25+
import static tech.tnze.msctf.WindowsException.checkResult;
26+
import static tech.tnze.msctf.windows.win32.ui.textservices.Constants.TS_SD_READONLY;
1727

1828
@Mixin(AbstractSignEditScreen.class)
1929
public class AbstractSignEditScreenMixin implements ACPSinkRegister {
2030
@Shadow
21-
private int line;
31+
public int line;
2232

23-
@Inject(method = "keyPressed", at = @At(value = "RETURN"))
33+
@Shadow
34+
@Nullable
35+
public TextFieldHelper signField;
36+
37+
@Shadow
38+
@Final
39+
public String[] messages;
40+
41+
@Inject(method = "keyPressed", at = @At("RETURN"))
2442
public void tnze$keyPressed(KeyEvent keyEvent, CallbackInfoReturnable<Boolean> cir) {
2543
if (keyEvent.isUp() || keyEvent.isDown()) {
2644
LOGGER.info("SignEditScreen line shifted to {}", this.line);
2745
Manager.getInstance().onScreenFocusedChange((AbstractSignEditScreen) (Object) this);
46+
} else if (sinkEnabled) {
47+
var sink = textStoreSink[this.line];
48+
if (sink != null) {
49+
checkResult(sink.OnSelectionChange());
50+
}
51+
}
52+
}
53+
54+
@Inject(method = "init", at = @At("TAIL"))
55+
protected void tnze$init(CallbackInfo ci) {
56+
if (!sinkEnabled) {
57+
return;
58+
}
59+
for (int i = 0; i < textStoreSink.length; i++) {
60+
var sink = textStoreSink[i];
61+
if (sink != null) {
62+
checkResult(sink.OnStatusChange(this.line == i && this.signField != null ? 0 : TS_SD_READONLY));
63+
try (var arena = Arena.ofConfined()) {
64+
var change = arena.allocate(TS_TEXTCHANGE.layout());
65+
TS_TEXTCHANGE.acpStart(change, 0);
66+
TS_TEXTCHANGE.acpOldEnd(change, 0);
67+
TS_TEXTCHANGE.acpNewEnd(change, this.messages[i].length());
68+
checkResult(sink.OnTextChange(0, change));
69+
}
70+
checkResult(sink.OnSelectionChange());
71+
}
72+
}
73+
}
74+
75+
@Unique
76+
private int changeStart, changeEnd;
77+
78+
@Inject(method = "setMessage", at = @At("HEAD"))
79+
protected void tnze$setMessage$head(String string, CallbackInfo ci) {
80+
changeStart = 0;
81+
changeEnd = this.messages[this.line].length();
82+
}
83+
84+
@Inject(method = "setMessage", at = @At("TAIL"))
85+
protected void tnze$setMessage(String string, CallbackInfo ci) {
86+
if (!sinkEnabled) {
87+
return;
88+
}
89+
var sink = textStoreSink[this.line];
90+
if (sink != null) {
91+
try (var arena = Arena.ofConfined()) {
92+
var change = arena.allocate(TS_TEXTCHANGE.layout());
93+
TS_TEXTCHANGE.acpStart(change, changeStart);
94+
TS_TEXTCHANGE.acpOldEnd(change, changeEnd);
95+
TS_TEXTCHANGE.acpNewEnd(change, string.length());
96+
checkResult(sink.OnTextChange(0, change));
97+
}
2898
}
2999
}
30100

31101
@Unique
32102
@Nullable
33-
private ITextStoreACPSink textStoreSink;
103+
private final ITextStoreACPSink[] textStoreSink = new ITextStoreACPSink[4];
34104

35105
@Unique
36106
private boolean sinkEnabled = true;
37107

38108
@Override
39-
public void tnze$registerACPSink(ITextStoreACPSink sink) {
40-
textStoreSink = sink;
109+
public void tnze$registerACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
110+
int line = ((SignEditLineACP) acpImpl).getLine();
111+
textStoreSink[line] = sink;
41112
}
42113

43114
@Override
44-
public void tnze$unregisterACPSink(ITextStoreACPSink sink) {
45-
assert sink.equals(textStoreSink);
46-
textStoreSink = null;
115+
public void tnze$unregisterACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
116+
int line = ((SignEditLineACP) acpImpl).getLine();
117+
assert sink.equals(textStoreSink[line]);
118+
textStoreSink[line] = null;
47119
}
48120

49121
@Override

src/client/java/tech/tnze/mixin/client/EditBoxMixin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.spongepowered.asm.mixin.injection.Inject;
1111
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
1212
import tech.tnze.client.ACPSinkRegister;
13+
import tech.tnze.client.AbstractTextFieldACP;
1314
import tech.tnze.msctf.windows.win32.ui.textservices.ITextStoreACPSink;
1415
import tech.tnze.msctf.windows.win32.ui.textservices.TS_TEXTCHANGE;
1516
import tech.tnze.msctf.windows.win32.ui.textservices.TsLayoutCode;
@@ -36,12 +37,12 @@ public abstract class EditBoxMixin implements ACPSinkRegister {
3637
private boolean sinkEnabled = true;
3738

3839
@Override
39-
public void tnze$registerACPSink(ITextStoreACPSink sink) {
40+
public void tnze$registerACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
4041
textStoreSink = sink;
4142
}
4243

4344
@Override
44-
public void tnze$unregisterACPSink(ITextStoreACPSink sink) {
45+
public void tnze$unregisterACPSink(AbstractTextFieldACP acpImpl, ITextStoreACPSink sink) {
4546
assert sink.equals(textStoreSink);
4647
textStoreSink = null;
4748
}

0 commit comments

Comments
 (0)