package jdk.internal.org.jline.terminal.impl;
import jdk.internal.org.jline.terminal.MouseEvent;
import jdk.internal.org.jline.terminal.Terminal;
import jdk.internal.org.jline.utils.InfoCmp;
import jdk.internal.org.jline.utils.InputStreamReader;
import java.io.EOFException;
import java.io.IOError;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.EnumSet;
import java.util.function.IntSupplier;
public class MouseSupport {
public static boolean hasMouseSupport(Terminal terminal) {
return terminal.getStringCapability(InfoCmp.Capability.key_mouse) != null;
}
public static boolean trackMouse(Terminal terminal, Terminal.MouseTracking tracking) {
if (hasMouseSupport(terminal)) {
switch (tracking) {
case Off:
terminal.writer().write("\033[?1000l");
break;
case Normal:
terminal.writer().write("\033[?1005h\033[?1000h");
break;
case Button:
terminal.writer().write("\033[?1005h\033[?1002h");
break;
case Any:
terminal.writer().write("\033[?1005h\033[?1003h");
break;
}
terminal.flush();
return true;
} else {
return false;
}
}
public static MouseEvent readMouse(Terminal terminal, MouseEvent last) {
return readMouse(() -> readExt(terminal), last);
}
public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) {
int cb = reader.getAsInt() - ' ';
int cx = reader.getAsInt() - ' ' - 1;
int cy = reader.getAsInt() - ' ' - 1;
MouseEvent.Type type;
MouseEvent.Button button;
EnumSet<MouseEvent.Modifier> modifiers = EnumSet.noneOf(MouseEvent.Modifier.class);
if ((cb & 4) == 4) {
modifiers.add(MouseEvent.Modifier.Shift);
}
if ((cb & 8) == 8) {
modifiers.add(MouseEvent.Modifier.Alt);
}
if ((cb & 16) == 16) {
modifiers.add(MouseEvent.Modifier.Control);
}
if ((cb & 64) == 64) {
type = MouseEvent.Type.Wheel;
button = (cb & 1) == 1 ? MouseEvent.Button.WheelDown : MouseEvent.Button.WheelUp;
} else {
int b = (cb & 3);
switch (b) {
case 0:
button = MouseEvent.Button.Button1;
if (last.getButton() == button
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
type = MouseEvent.Type.Dragged;
} else {
type = MouseEvent.Type.Pressed;
}
break;
case 1:
button = MouseEvent.Button.Button2;
if (last.getButton() == button
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
type = MouseEvent.Type.Dragged;
} else {
type = MouseEvent.Type.Pressed;
}
break;
case 2:
button = MouseEvent.Button.Button3;
if (last.getButton() == button
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
type = MouseEvent.Type.Dragged;
} else {
type = MouseEvent.Type.Pressed;
}
break;
default:
if (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged) {
button = last.getButton();
type = MouseEvent.Type.Released;
} else {
button = MouseEvent.Button.NoButton;
type = MouseEvent.Type.Moved;
}
break;
}
}
return new MouseEvent(type, button, modifiers, cx, cy);
}
private static int readExt(Terminal terminal) {
try {
int c;
if (terminal.encoding() != StandardCharsets.UTF_8) {
c = new InputStreamReader(terminal.input(), StandardCharsets.UTF_8).read();
} else {
c = terminal.reader().read();
}
if (c < 0) {
throw new EOFException();
}
return c;
} catch (IOException e) {
throw new IOError(e);
}
}
}