// 
// Decompiled by Procyon v0.6.0
// 

package org.jline.terminal.impl.ffm;

import java.util.Objects;
import java.lang.foreign.GroupLayout;
import java.lang.invoke.VarHandle;
import java.lang.foreign.Linker;
import java.lang.foreign.FunctionDescriptor;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
import java.lang.foreign.MemoryLayout;
import java.io.IOException;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.invoke.MethodHandle;
import java.lang.foreign.AddressLayout;
import java.lang.foreign.ValueLayout;
import java.lang.foreign.SymbolLookup;

final class Kernel32
{
    public static final int FORMAT_MESSAGE_FROM_SYSTEM = 4096;
    public static final long INVALID_HANDLE_VALUE = -1L;
    public static final int STD_INPUT_HANDLE = -10;
    public static final int STD_OUTPUT_HANDLE = -11;
    public static final int STD_ERROR_HANDLE = -12;
    public static final int ENABLE_PROCESSED_INPUT = 1;
    public static final int ENABLE_LINE_INPUT = 2;
    public static final int ENABLE_ECHO_INPUT = 4;
    public static final int ENABLE_WINDOW_INPUT = 8;
    public static final int ENABLE_MOUSE_INPUT = 16;
    public static final int ENABLE_INSERT_MODE = 32;
    public static final int ENABLE_QUICK_EDIT_MODE = 64;
    public static final int ENABLE_EXTENDED_FLAGS = 128;
    public static final int RIGHT_ALT_PRESSED = 1;
    public static final int LEFT_ALT_PRESSED = 2;
    public static final int RIGHT_CTRL_PRESSED = 4;
    public static final int LEFT_CTRL_PRESSED = 8;
    public static final int SHIFT_PRESSED = 16;
    public static final int FOREGROUND_BLUE = 1;
    public static final int FOREGROUND_GREEN = 2;
    public static final int FOREGROUND_RED = 4;
    public static final int FOREGROUND_INTENSITY = 8;
    public static final int BACKGROUND_BLUE = 16;
    public static final int BACKGROUND_GREEN = 32;
    public static final int BACKGROUND_RED = 64;
    public static final int BACKGROUND_INTENSITY = 128;
    public static final int FROM_LEFT_1ST_BUTTON_PRESSED = 1;
    public static final int RIGHTMOST_BUTTON_PRESSED = 2;
    public static final int FROM_LEFT_2ND_BUTTON_PRESSED = 4;
    public static final int FROM_LEFT_3RD_BUTTON_PRESSED = 8;
    public static final int FROM_LEFT_4TH_BUTTON_PRESSED = 16;
    public static final int MOUSE_MOVED = 1;
    public static final int DOUBLE_CLICK = 2;
    public static final int MOUSE_WHEELED = 4;
    public static final int MOUSE_HWHEELED = 8;
    public static final short KEY_EVENT = 1;
    public static final short MOUSE_EVENT = 2;
    public static final short WINDOW_BUFFER_SIZE_EVENT = 4;
    public static final short MENU_EVENT = 8;
    public static final short FOCUS_EVENT = 16;
    private static final SymbolLookup SYMBOL_LOOKUP;
    static final ValueLayout.OfBoolean C_BOOL$LAYOUT;
    static final ValueLayout.OfByte C_CHAR$LAYOUT;
    static final ValueLayout.OfChar C_WCHAR$LAYOUT;
    static final ValueLayout.OfShort C_SHORT$LAYOUT;
    static final ValueLayout.OfShort C_WORD$LAYOUT;
    static final ValueLayout.OfInt C_DWORD$LAYOUT;
    static final ValueLayout.OfInt C_INT$LAYOUT;
    static final ValueLayout.OfLong C_LONG$LAYOUT;
    static final ValueLayout.OfLong C_LONG_LONG$LAYOUT;
    static final ValueLayout.OfFloat C_FLOAT$LAYOUT;
    static final ValueLayout.OfDouble C_DOUBLE$LAYOUT;
    static final AddressLayout C_POINTER$LAYOUT;
    static final MethodHandle WaitForSingleObject$MH;
    static final MethodHandle GetStdHandle$MH;
    static final MethodHandle FormatMessageW$MH;
    static final MethodHandle SetConsoleTextAttribute$MH;
    static final MethodHandle SetConsoleMode$MH;
    static final MethodHandle GetConsoleMode$MH;
    static final MethodHandle SetConsoleTitleW$MH;
    static final MethodHandle SetConsoleCursorPosition$MH;
    static final MethodHandle FillConsoleOutputCharacterW$MH;
    static final MethodHandle FillConsoleOutputAttribute$MH;
    static final MethodHandle WriteConsoleW$MH;
    static final MethodHandle ReadConsoleInputW$MH;
    static final MethodHandle PeekConsoleInputW$MH;
    static final MethodHandle GetConsoleScreenBufferInfo$MH;
    static final MethodHandle ScrollConsoleScreenBufferW$MH;
    static final MethodHandle GetLastError$MH;
    static final MethodHandle GetFileType$MH;
    static final MethodHandle _get_osfhandle$MH;
    
    public static int WaitForSingleObject(final MemorySegment hHandle, final int dwMilliseconds) {
        final MethodHandle mh$ = requireNonNull(Kernel32.WaitForSingleObject$MH, "WaitForSingleObject");
        try {
            return mh$.invokeExact(hHandle, dwMilliseconds);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static MemorySegment GetStdHandle(final int nStdHandle) {
        final MethodHandle mh$ = requireNonNull(Kernel32.GetStdHandle$MH, "GetStdHandle");
        try {
            return mh$.invokeExact(nStdHandle);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int FormatMessageW(final int dwFlags, final MemorySegment lpSource, final int dwMessageId, final int dwLanguageId, final MemorySegment lpBuffer, final int nSize, final MemorySegment Arguments) {
        final MethodHandle mh$ = requireNonNull(Kernel32.FormatMessageW$MH, "FormatMessageW");
        try {
            return mh$.invokeExact(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int SetConsoleTextAttribute(final MemorySegment hConsoleOutput, final short wAttributes) {
        final MethodHandle mh$ = requireNonNull(Kernel32.SetConsoleTextAttribute$MH, "SetConsoleTextAttribute");
        try {
            return mh$.invokeExact(hConsoleOutput, wAttributes);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int SetConsoleMode(final MemorySegment hConsoleHandle, final int dwMode) {
        final MethodHandle mh$ = requireNonNull(Kernel32.SetConsoleMode$MH, "SetConsoleMode");
        try {
            return mh$.invokeExact(hConsoleHandle, dwMode);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int GetConsoleMode(final MemorySegment hConsoleHandle, final MemorySegment lpMode) {
        final MethodHandle mh$ = requireNonNull(Kernel32.GetConsoleMode$MH, "GetConsoleMode");
        try {
            return mh$.invokeExact(hConsoleHandle, lpMode);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int SetConsoleTitleW(final MemorySegment lpConsoleTitle) {
        final MethodHandle mh$ = requireNonNull(Kernel32.SetConsoleTitleW$MH, "SetConsoleTitleW");
        try {
            return mh$.invokeExact(lpConsoleTitle);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int SetConsoleCursorPosition(final MemorySegment hConsoleOutput, final COORD dwCursorPosition) {
        final MethodHandle mh$ = requireNonNull(Kernel32.SetConsoleCursorPosition$MH, "SetConsoleCursorPosition");
        try {
            return mh$.invokeExact(hConsoleOutput, dwCursorPosition.seg);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int FillConsoleOutputCharacterW(final MemorySegment hConsoleOutput, final char cCharacter, final int nLength, final COORD dwWriteCoord, final MemorySegment lpNumberOfCharsWritten) {
        final MethodHandle mh$ = requireNonNull(Kernel32.FillConsoleOutputCharacterW$MH, "FillConsoleOutputCharacterW");
        try {
            return mh$.invokeExact(hConsoleOutput, cCharacter, nLength, dwWriteCoord.seg, lpNumberOfCharsWritten);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int FillConsoleOutputAttribute(final MemorySegment hConsoleOutput, final short wAttribute, final int nLength, final COORD dwWriteCoord, final MemorySegment lpNumberOfAttrsWritten) {
        final MethodHandle mh$ = requireNonNull(Kernel32.FillConsoleOutputAttribute$MH, "FillConsoleOutputAttribute");
        try {
            return mh$.invokeExact(hConsoleOutput, wAttribute, nLength, dwWriteCoord.seg, lpNumberOfAttrsWritten);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int WriteConsoleW(final MemorySegment hConsoleOutput, final MemorySegment lpBuffer, final int nNumberOfCharsToWrite, final MemorySegment lpNumberOfCharsWritten, final MemorySegment lpReserved) {
        final MethodHandle mh$ = requireNonNull(Kernel32.WriteConsoleW$MH, "WriteConsoleW");
        try {
            return mh$.invokeExact(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int ReadConsoleInputW(final MemorySegment hConsoleInput, final MemorySegment lpBuffer, final int nLength, final MemorySegment lpNumberOfEventsRead) {
        final MethodHandle mh$ = requireNonNull(Kernel32.ReadConsoleInputW$MH, "ReadConsoleInputW");
        try {
            return mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int PeekConsoleInputW(final MemorySegment hConsoleInput, final MemorySegment lpBuffer, final int nLength, final MemorySegment lpNumberOfEventsRead) {
        final MethodHandle mh$ = requireNonNull(Kernel32.PeekConsoleInputW$MH, "PeekConsoleInputW");
        try {
            return mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int GetConsoleScreenBufferInfo(final MemorySegment hConsoleOutput, final CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) {
        final MethodHandle mh$ = requireNonNull(Kernel32.GetConsoleScreenBufferInfo$MH, "GetConsoleScreenBufferInfo");
        try {
            return mh$.invokeExact(hConsoleOutput, lpConsoleScreenBufferInfo.seg);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int ScrollConsoleScreenBuffer(final MemorySegment hConsoleOutput, final SMALL_RECT lpScrollRectangle, final SMALL_RECT lpClipRectangle, final COORD dwDestinationOrigin, final CHAR_INFO lpFill) {
        final MethodHandle mh$ = requireNonNull(Kernel32.ScrollConsoleScreenBufferW$MH, "ScrollConsoleScreenBuffer");
        try {
            return mh$.invokeExact(hConsoleOutput, lpScrollRectangle.seg, lpClipRectangle.seg, dwDestinationOrigin.seg, lpFill.seg);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int GetLastError() {
        final MethodHandle mh$ = requireNonNull(Kernel32.GetLastError$MH, "GetLastError");
        try {
            return mh$.invokeExact();
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static int GetFileType(final MemorySegment hFile) {
        final MethodHandle mh$ = requireNonNull(Kernel32.GetFileType$MH, "GetFileType");
        try {
            return mh$.invokeExact(hFile);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static MemorySegment _get_osfhandle(final int fd) {
        final MethodHandle mh$ = requireNonNull(Kernel32._get_osfhandle$MH, "_get_osfhandle");
        try {
            return mh$.invokeExact(fd);
        }
        catch (final Throwable ex$) {
            throw new AssertionError("should not reach here", ex$);
        }
    }
    
    public static INPUT_RECORD[] readConsoleInputHelper(final MemorySegment handle, final int count, final boolean peek) throws IOException {
        return readConsoleInputHelper(Arena.ofAuto(), handle, count, peek);
    }
    
    public static INPUT_RECORD[] readConsoleInputHelper(final Arena arena, final MemorySegment handle, final int count, final boolean peek) throws IOException {
        final MemorySegment inputRecordPtr = arena.allocate(INPUT_RECORD.LAYOUT, (long)count);
        final MemorySegment length = arena.allocate((MemoryLayout)ValueLayout.JAVA_INT, 1L);
        final int res = peek ? PeekConsoleInputW(handle, inputRecordPtr, count, length) : ReadConsoleInputW(handle, inputRecordPtr, count, length);
        if (res == 0) {
            throw new IOException("ReadConsoleInputW failed: " + getLastErrorMessage());
        }
        final int len = length.get(ValueLayout.JAVA_INT, 0L);
        return inputRecordPtr.elements(INPUT_RECORD.LAYOUT).map((Function<? super MemorySegment, ?>)INPUT_RECORD::new).limit(len).toArray(INPUT_RECORD[]::new);
    }
    
    public static String getLastErrorMessage() {
        final int errorCode = GetLastError();
        return getErrorMessage(errorCode);
    }
    
    public static String getErrorMessage(final int errorCode) {
        final int bufferSize = 160;
        try (final Arena arena = Arena.ofConfined()) {
            final MemorySegment data = arena.allocate(bufferSize);
            FormatMessageW(4096, MemorySegment.NULL, errorCode, 0, data, bufferSize, MemorySegment.NULL);
            return new String(data.toArray(ValueLayout.JAVA_BYTE), StandardCharsets.UTF_16LE).trim();
        }
    }
    
    static MethodHandle downcallHandle(final String name, final FunctionDescriptor fdesc) {
        return Kernel32.SYMBOL_LOOKUP.find(name).map(addr -> Linker.nativeLinker().downcallHandle(addr, fdesc, new Linker.Option[0])).orElse(null);
    }
    
    static <T> T requireNonNull(final T obj, final String symbolName) {
        if (obj == null) {
            throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName);
        }
        return obj;
    }
    
    static VarHandle varHandle(final MemoryLayout layout, final String name) {
        return FfmTerminalProvider.lookupVarHandle(layout, MemoryLayout.PathElement.groupElement(name));
    }
    
    static VarHandle varHandle(final MemoryLayout layout, final String e1, final String name) {
        return FfmTerminalProvider.lookupVarHandle(layout, MemoryLayout.PathElement.groupElement(e1), MemoryLayout.PathElement.groupElement(name));
    }
    
    static long byteOffset(final MemoryLayout layout, final String name) {
        return layout.byteOffset(MemoryLayout.PathElement.groupElement(name));
    }
    
    static {
        System.loadLibrary("msvcrt");
        System.loadLibrary("Kernel32");
        SYMBOL_LOOKUP = SymbolLookup.loaderLookup();
        C_BOOL$LAYOUT = ValueLayout.JAVA_BOOLEAN;
        C_CHAR$LAYOUT = ValueLayout.JAVA_BYTE;
        C_WCHAR$LAYOUT = ValueLayout.JAVA_CHAR;
        C_SHORT$LAYOUT = ValueLayout.JAVA_SHORT;
        C_WORD$LAYOUT = ValueLayout.JAVA_SHORT;
        C_DWORD$LAYOUT = ValueLayout.JAVA_INT;
        C_INT$LAYOUT = ValueLayout.JAVA_INT;
        C_LONG$LAYOUT = ValueLayout.JAVA_LONG;
        C_LONG_LONG$LAYOUT = ValueLayout.JAVA_LONG;
        C_FLOAT$LAYOUT = ValueLayout.JAVA_FLOAT;
        C_DOUBLE$LAYOUT = ValueLayout.JAVA_DOUBLE;
        C_POINTER$LAYOUT = ValueLayout.ADDRESS;
        WaitForSingleObject$MH = downcallHandle("WaitForSingleObject", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT));
        GetStdHandle$MH = downcallHandle("GetStdHandle", FunctionDescriptor.of(Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT));
        FormatMessageW$MH = downcallHandle("FormatMessageW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        SetConsoleTextAttribute$MH = downcallHandle("SetConsoleTextAttribute", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_SHORT$LAYOUT));
        SetConsoleMode$MH = downcallHandle("SetConsoleMode", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT));
        GetConsoleMode$MH = downcallHandle("GetConsoleMode", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        SetConsoleTitleW$MH = downcallHandle("SetConsoleTitleW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        SetConsoleCursorPosition$MH = downcallHandle("SetConsoleCursorPosition", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, COORD.LAYOUT));
        FillConsoleOutputCharacterW$MH = downcallHandle("FillConsoleOutputCharacterW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_WCHAR$LAYOUT, Kernel32.C_INT$LAYOUT, COORD.LAYOUT, Kernel32.C_POINTER$LAYOUT));
        FillConsoleOutputAttribute$MH = downcallHandle("FillConsoleOutputAttribute", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_SHORT$LAYOUT, Kernel32.C_INT$LAYOUT, COORD.LAYOUT, Kernel32.C_POINTER$LAYOUT));
        WriteConsoleW$MH = downcallHandle("WriteConsoleW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        ReadConsoleInputW$MH = downcallHandle("ReadConsoleInputW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        PeekConsoleInputW$MH = downcallHandle("PeekConsoleInputW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        GetConsoleScreenBufferInfo$MH = downcallHandle("GetConsoleScreenBufferInfo", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        ScrollConsoleScreenBufferW$MH = downcallHandle("ScrollConsoleScreenBufferW", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT, Kernel32.C_POINTER$LAYOUT, COORD.LAYOUT, Kernel32.C_POINTER$LAYOUT));
        GetLastError$MH = downcallHandle("GetLastError", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, new MemoryLayout[0]));
        GetFileType$MH = downcallHandle("GetFileType", FunctionDescriptor.of(Kernel32.C_INT$LAYOUT, Kernel32.C_POINTER$LAYOUT));
        _get_osfhandle$MH = downcallHandle("_get_osfhandle", FunctionDescriptor.of(Kernel32.C_POINTER$LAYOUT, Kernel32.C_INT$LAYOUT));
    }
    
    public static final class INPUT_RECORD
    {
        static final MemoryLayout LAYOUT;
        static final VarHandle EventType$VH;
        static final long Event$OFFSET;
        private final MemorySegment seg;
        
        public INPUT_RECORD() {
            this(Arena.ofAuto());
        }
        
        public INPUT_RECORD(final Arena arena) {
            this(arena.allocate(INPUT_RECORD.LAYOUT));
        }
        
        public INPUT_RECORD(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public short eventType() {
            return INPUT_RECORD.EventType$VH.get(this.seg);
        }
        
        public KEY_EVENT_RECORD keyEvent() {
            return new KEY_EVENT_RECORD(this.seg, INPUT_RECORD.Event$OFFSET);
        }
        
        public MOUSE_EVENT_RECORD mouseEvent() {
            return new MOUSE_EVENT_RECORD(this.seg, INPUT_RECORD.Event$OFFSET);
        }
        
        public FOCUS_EVENT_RECORD focusEvent() {
            return new FOCUS_EVENT_RECORD(this.seg, INPUT_RECORD.Event$OFFSET);
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(ValueLayout.JAVA_SHORT.withName("EventType"), ValueLayout.JAVA_SHORT, MemoryLayout.unionLayout(KEY_EVENT_RECORD.LAYOUT.withName("KeyEvent"), MOUSE_EVENT_RECORD.LAYOUT.withName("MouseEvent"), WINDOW_BUFFER_SIZE_RECORD.LAYOUT.withName("WindowBufferSizeEvent"), MENU_EVENT_RECORD.LAYOUT.withName("MenuEvent"), FOCUS_EVENT_RECORD.LAYOUT.withName("FocusEvent")).withName("Event"));
            EventType$VH = Kernel32.varHandle(INPUT_RECORD.LAYOUT, "EventType");
            Event$OFFSET = Kernel32.byteOffset(INPUT_RECORD.LAYOUT, "Event");
        }
    }
    
    public static final class MENU_EVENT_RECORD
    {
        static final GroupLayout LAYOUT;
        static final VarHandle COMMAND_ID;
        private final MemorySegment seg;
        
        public MENU_EVENT_RECORD() {
            this(Arena.ofAuto());
        }
        
        public MENU_EVENT_RECORD(final Arena arena) {
            this(arena.allocate(MENU_EVENT_RECORD.LAYOUT));
        }
        
        public MENU_EVENT_RECORD(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public int commandId() {
            return MENU_EVENT_RECORD.COMMAND_ID.get(this.seg);
        }
        
        public void commandId(final int commandId) {
            MENU_EVENT_RECORD.COMMAND_ID.set(this.seg, commandId);
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(Kernel32.C_DWORD$LAYOUT.withName("dwCommandId"));
            COMMAND_ID = Kernel32.varHandle(MENU_EVENT_RECORD.LAYOUT, "dwCommandId");
        }
    }
    
    public static final class FOCUS_EVENT_RECORD
    {
        static final GroupLayout LAYOUT;
        static final VarHandle SET_FOCUS;
        private final MemorySegment seg;
        
        public FOCUS_EVENT_RECORD() {
            this(Arena.ofAuto());
        }
        
        public FOCUS_EVENT_RECORD(final Arena arena) {
            this(arena.allocate(FOCUS_EVENT_RECORD.LAYOUT));
        }
        
        public FOCUS_EVENT_RECORD(final MemorySegment seg) {
            this.seg = Objects.requireNonNull(seg);
        }
        
        public FOCUS_EVENT_RECORD(final MemorySegment seg, final long offset) {
            this.seg = Objects.requireNonNull(seg).asSlice(offset, FOCUS_EVENT_RECORD.LAYOUT.byteSize());
        }
        
        public boolean setFocus() {
            return FOCUS_EVENT_RECORD.SET_FOCUS.get(this.seg) != 0;
        }
        
        public void setFocus(final boolean setFocus) {
            FOCUS_EVENT_RECORD.SET_FOCUS.set(this.seg, (int)(setFocus ? 1 : 0));
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(Kernel32.C_INT$LAYOUT.withName("bSetFocus"));
            SET_FOCUS = Kernel32.varHandle(FOCUS_EVENT_RECORD.LAYOUT, "bSetFocus");
        }
    }
    
    public static final class WINDOW_BUFFER_SIZE_RECORD
    {
        static final GroupLayout LAYOUT;
        static final long SIZE_OFFSET;
        private final MemorySegment seg;
        
        public WINDOW_BUFFER_SIZE_RECORD() {
            this(Arena.ofAuto());
        }
        
        public WINDOW_BUFFER_SIZE_RECORD(final Arena arena) {
            this(arena.allocate(WINDOW_BUFFER_SIZE_RECORD.LAYOUT));
        }
        
        public WINDOW_BUFFER_SIZE_RECORD(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public COORD size() {
            return new COORD(this.seg, WINDOW_BUFFER_SIZE_RECORD.SIZE_OFFSET);
        }
        
        @Override
        public String toString() {
            return "WINDOW_BUFFER_SIZE_RECORD{size=" + String.valueOf(this.size());
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(COORD.LAYOUT.withName("size"));
            SIZE_OFFSET = Kernel32.byteOffset(WINDOW_BUFFER_SIZE_RECORD.LAYOUT, "size");
        }
    }
    
    public static final class MOUSE_EVENT_RECORD
    {
        static final MemoryLayout LAYOUT;
        static final long MOUSE_POSITION_OFFSET;
        static final VarHandle BUTTON_STATE;
        static final VarHandle CONTROL_KEY_STATE;
        static final VarHandle EVENT_FLAGS;
        private final MemorySegment seg;
        
        public MOUSE_EVENT_RECORD() {
            this(Arena.ofAuto());
        }
        
        public MOUSE_EVENT_RECORD(final Arena arena) {
            this(arena.allocate(MOUSE_EVENT_RECORD.LAYOUT));
        }
        
        public MOUSE_EVENT_RECORD(final MemorySegment seg) {
            this.seg = Objects.requireNonNull(seg);
        }
        
        public MOUSE_EVENT_RECORD(final MemorySegment seg, final long offset) {
            this.seg = Objects.requireNonNull(seg).asSlice(offset, MOUSE_EVENT_RECORD.LAYOUT.byteSize());
        }
        
        public COORD mousePosition() {
            return new COORD(this.seg, MOUSE_EVENT_RECORD.MOUSE_POSITION_OFFSET);
        }
        
        public int buttonState() {
            return MOUSE_EVENT_RECORD.BUTTON_STATE.get(this.seg);
        }
        
        public int controlKeyState() {
            return MOUSE_EVENT_RECORD.CONTROL_KEY_STATE.get(this.seg);
        }
        
        public int eventFlags() {
            return MOUSE_EVENT_RECORD.EVENT_FLAGS.get(this.seg);
        }
        
        @Override
        public String toString() {
            return "MOUSE_EVENT_RECORD{mousePosition=" + String.valueOf(this.mousePosition()) + ", buttonState=" + this.buttonState() + ", controlKeyState=" + this.controlKeyState() + ", eventFlags=" + this.eventFlags();
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(COORD.LAYOUT.withName("dwMousePosition"), Kernel32.C_DWORD$LAYOUT.withName("dwButtonState"), Kernel32.C_DWORD$LAYOUT.withName("dwControlKeyState"), Kernel32.C_DWORD$LAYOUT.withName("dwEventFlags"));
            MOUSE_POSITION_OFFSET = Kernel32.byteOffset(MOUSE_EVENT_RECORD.LAYOUT, "dwMousePosition");
            BUTTON_STATE = Kernel32.varHandle(MOUSE_EVENT_RECORD.LAYOUT, "dwButtonState");
            CONTROL_KEY_STATE = Kernel32.varHandle(MOUSE_EVENT_RECORD.LAYOUT, "dwControlKeyState");
            EVENT_FLAGS = Kernel32.varHandle(MOUSE_EVENT_RECORD.LAYOUT, "dwEventFlags");
        }
    }
    
    public static final class KEY_EVENT_RECORD
    {
        static final MemoryLayout LAYOUT;
        static final VarHandle bKeyDown$VH;
        static final VarHandle wRepeatCount$VH;
        static final VarHandle wVirtualKeyCode$VH;
        static final VarHandle wVirtualScanCode$VH;
        static final VarHandle UnicodeChar$VH;
        static final VarHandle AsciiChar$VH;
        static final VarHandle dwControlKeyState$VH;
        final MemorySegment seg;
        
        public KEY_EVENT_RECORD() {
            this(Arena.ofAuto());
        }
        
        public KEY_EVENT_RECORD(final Arena arena) {
            this(arena.allocate(KEY_EVENT_RECORD.LAYOUT));
        }
        
        public KEY_EVENT_RECORD(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public KEY_EVENT_RECORD(final MemorySegment seg, final long offset) {
            this.seg = Objects.requireNonNull(seg).asSlice(offset, KEY_EVENT_RECORD.LAYOUT.byteSize());
        }
        
        public boolean keyDown() {
            return KEY_EVENT_RECORD.bKeyDown$VH.get(this.seg) != 0;
        }
        
        public int repeatCount() {
            return KEY_EVENT_RECORD.wRepeatCount$VH.get(this.seg);
        }
        
        public short keyCode() {
            return KEY_EVENT_RECORD.wVirtualKeyCode$VH.get(this.seg);
        }
        
        public short scanCode() {
            return KEY_EVENT_RECORD.wVirtualScanCode$VH.get(this.seg);
        }
        
        public char uchar() {
            return KEY_EVENT_RECORD.UnicodeChar$VH.get(this.seg);
        }
        
        public int controlKeyState() {
            return KEY_EVENT_RECORD.dwControlKeyState$VH.get(this.seg);
        }
        
        @Override
        public String toString() {
            return "KEY_EVENT_RECORD{keyDown=" + this.keyDown() + ", repeatCount=" + this.repeatCount() + ", keyCode=" + this.keyCode() + ", scanCode=" + this.scanCode() + ", uchar=" + this.uchar() + ", controlKeyState=" + this.controlKeyState();
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(ValueLayout.JAVA_INT.withName("bKeyDown"), ValueLayout.JAVA_SHORT.withName("wRepeatCount"), ValueLayout.JAVA_SHORT.withName("wVirtualKeyCode"), ValueLayout.JAVA_SHORT.withName("wVirtualScanCode"), MemoryLayout.unionLayout(ValueLayout.JAVA_CHAR.withName("UnicodeChar"), ValueLayout.JAVA_BYTE.withName("AsciiChar")).withName("uChar"), ValueLayout.JAVA_INT.withName("dwControlKeyState"));
            bKeyDown$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "bKeyDown");
            wRepeatCount$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "wRepeatCount");
            wVirtualKeyCode$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "wVirtualKeyCode");
            wVirtualScanCode$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "wVirtualScanCode");
            UnicodeChar$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "uChar", "UnicodeChar");
            AsciiChar$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "uChar", "AsciiChar");
            dwControlKeyState$VH = Kernel32.varHandle(KEY_EVENT_RECORD.LAYOUT, "dwControlKeyState");
        }
    }
    
    public static final class CHAR_INFO
    {
        static final GroupLayout LAYOUT;
        static final VarHandle UnicodeChar$VH;
        static final VarHandle Attributes$VH;
        final MemorySegment seg;
        
        public CHAR_INFO() {
            this(Arena.ofAuto());
        }
        
        public CHAR_INFO(final Arena arena) {
            this(arena.allocate(CHAR_INFO.LAYOUT));
        }
        
        public CHAR_INFO(final Arena arena, final char c, final short a) {
            this(arena);
            CHAR_INFO.UnicodeChar$VH.set(this.seg, c);
            CHAR_INFO.Attributes$VH.set(this.seg, a);
        }
        
        public CHAR_INFO(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public char unicodeChar() {
            return CHAR_INFO.UnicodeChar$VH.get(this.seg);
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(MemoryLayout.unionLayout(Kernel32.C_WCHAR$LAYOUT.withName("UnicodeChar"), Kernel32.C_CHAR$LAYOUT.withName("AsciiChar")).withName("Char"), Kernel32.C_WORD$LAYOUT.withName("Attributes"));
            UnicodeChar$VH = Kernel32.varHandle(CHAR_INFO.LAYOUT, "Char", "UnicodeChar");
            Attributes$VH = Kernel32.varHandle(CHAR_INFO.LAYOUT, "Attributes");
        }
    }
    
    public static final class CONSOLE_SCREEN_BUFFER_INFO
    {
        static final GroupLayout LAYOUT;
        static final long dwSize$OFFSET;
        static final long dwCursorPosition$OFFSET;
        static final VarHandle wAttributes$VH;
        static final long srWindow$OFFSET;
        private final MemorySegment seg;
        
        public CONSOLE_SCREEN_BUFFER_INFO() {
            this(Arena.ofAuto());
        }
        
        public CONSOLE_SCREEN_BUFFER_INFO(final Arena arena) {
            this(arena.allocate(CONSOLE_SCREEN_BUFFER_INFO.LAYOUT));
        }
        
        public CONSOLE_SCREEN_BUFFER_INFO(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public COORD size() {
            return new COORD(this.seg, CONSOLE_SCREEN_BUFFER_INFO.dwSize$OFFSET);
        }
        
        public COORD cursorPosition() {
            return new COORD(this.seg, CONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition$OFFSET);
        }
        
        public short attributes() {
            return CONSOLE_SCREEN_BUFFER_INFO.wAttributes$VH.get(this.seg);
        }
        
        public SMALL_RECT window() {
            return new SMALL_RECT(this.seg, CONSOLE_SCREEN_BUFFER_INFO.srWindow$OFFSET);
        }
        
        public int windowWidth() {
            return this.window().width() + 1;
        }
        
        public int windowHeight() {
            return this.window().height() + 1;
        }
        
        public void attributes(final short attr) {
            CONSOLE_SCREEN_BUFFER_INFO.wAttributes$VH.set(this.seg, attr);
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(COORD.LAYOUT.withName("dwSize"), COORD.LAYOUT.withName("dwCursorPosition"), Kernel32.C_WORD$LAYOUT.withName("wAttributes"), SMALL_RECT.LAYOUT.withName("srWindow"), COORD.LAYOUT.withName("dwMaximumWindowSize"));
            dwSize$OFFSET = Kernel32.byteOffset(CONSOLE_SCREEN_BUFFER_INFO.LAYOUT, "dwSize");
            dwCursorPosition$OFFSET = Kernel32.byteOffset(CONSOLE_SCREEN_BUFFER_INFO.LAYOUT, "dwCursorPosition");
            wAttributes$VH = Kernel32.varHandle(CONSOLE_SCREEN_BUFFER_INFO.LAYOUT, "wAttributes");
            srWindow$OFFSET = Kernel32.byteOffset(CONSOLE_SCREEN_BUFFER_INFO.LAYOUT, "srWindow");
        }
    }
    
    public static final class COORD
    {
        static final GroupLayout LAYOUT;
        static final VarHandle x$VH;
        static final VarHandle y$VH;
        private final MemorySegment seg;
        
        public COORD() {
            this(Arena.ofAuto());
        }
        
        public COORD(final Arena arena) {
            this(arena.allocate(COORD.LAYOUT));
        }
        
        public COORD(final Arena arena, final short x, final short y) {
            this(arena.allocate(COORD.LAYOUT));
            this.x(x);
            this.y(y);
        }
        
        public COORD(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public COORD(final MemorySegment seg, final long offset) {
            this.seg = Objects.requireNonNull(seg).asSlice(offset, COORD.LAYOUT.byteSize());
        }
        
        public short x() {
            return COORD.x$VH.get(this.seg);
        }
        
        public void x(final short x) {
            COORD.x$VH.set(this.seg, x);
        }
        
        public short y() {
            return COORD.y$VH.get(this.seg);
        }
        
        public void y(final short y) {
            COORD.y$VH.set(this.seg, y);
        }
        
        public COORD copy(final Arena arena) {
            return new COORD(arena.allocate(COORD.LAYOUT).copyFrom(this.seg));
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(Kernel32.C_SHORT$LAYOUT.withName("x"), Kernel32.C_SHORT$LAYOUT.withName("y"));
            x$VH = Kernel32.varHandle(COORD.LAYOUT, "x");
            y$VH = Kernel32.varHandle(COORD.LAYOUT, "y");
        }
    }
    
    public static final class SMALL_RECT
    {
        static final GroupLayout LAYOUT;
        static final VarHandle Left$VH;
        static final VarHandle Top$VH;
        static final VarHandle Right$VH;
        static final VarHandle Bottom$VH;
        private final MemorySegment seg;
        
        public SMALL_RECT() {
            this(Arena.ofAuto());
        }
        
        public SMALL_RECT(final Arena arena) {
            this(arena.allocate(SMALL_RECT.LAYOUT));
        }
        
        public SMALL_RECT(final Arena arena, final SMALL_RECT rect) {
            this(arena);
            this.left(rect.left());
            this.right(rect.right());
            this.top(rect.top());
            this.bottom(rect.bottom());
        }
        
        public SMALL_RECT(final MemorySegment seg, final long offset) {
            this(seg.asSlice(offset, SMALL_RECT.LAYOUT.byteSize()));
        }
        
        public SMALL_RECT(final MemorySegment seg) {
            this.seg = seg;
        }
        
        public short left() {
            return SMALL_RECT.Left$VH.get(this.seg);
        }
        
        public short top() {
            return SMALL_RECT.Top$VH.get(this.seg);
        }
        
        public short right() {
            return SMALL_RECT.Right$VH.get(this.seg);
        }
        
        public short bottom() {
            return SMALL_RECT.Bottom$VH.get(this.seg);
        }
        
        public short width() {
            return (short)(this.right() - this.left());
        }
        
        public short height() {
            return (short)(this.bottom() - this.top());
        }
        
        public void left(final short l) {
            SMALL_RECT.Left$VH.set(this.seg, l);
        }
        
        public void top(final short t) {
            SMALL_RECT.Top$VH.set(this.seg, t);
        }
        
        public void right(final short r) {
            SMALL_RECT.Right$VH.set(this.seg, r);
        }
        
        public void bottom(final short b) {
            SMALL_RECT.Bottom$VH.set(this.seg, b);
        }
        
        public SMALL_RECT copy(final Arena arena) {
            return new SMALL_RECT(arena.allocate(SMALL_RECT.LAYOUT).copyFrom(this.seg));
        }
        
        static {
            LAYOUT = MemoryLayout.structLayout(Kernel32.C_SHORT$LAYOUT.withName("Left"), Kernel32.C_SHORT$LAYOUT.withName("Top"), Kernel32.C_SHORT$LAYOUT.withName("Right"), Kernel32.C_SHORT$LAYOUT.withName("Bottom"));
            Left$VH = Kernel32.varHandle(SMALL_RECT.LAYOUT, "Left");
            Top$VH = Kernel32.varHandle(SMALL_RECT.LAYOUT, "Top");
            Right$VH = Kernel32.varHandle(SMALL_RECT.LAYOUT, "Right");
            Bottom$VH = Kernel32.varHandle(SMALL_RECT.LAYOUT, "Bottom");
        }
    }
}
