001/*
002 * Copyright (C) 2009-2017 the original author(s).
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fusesource.jansi.internal;
017
018import org.fusesource.hawtjni.runtime.*;
019
020import java.io.IOException;
021
022import static org.fusesource.hawtjni.runtime.ArgFlag.*;
023import static org.fusesource.hawtjni.runtime.ClassFlag.*;
024import static org.fusesource.hawtjni.runtime.FieldFlag.*;
025import static org.fusesource.hawtjni.runtime.MethodFlag.*;
026
027/**
028 * Interface to access Win32 base APIs.
029 *
030 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
031 */
032@JniClass(conditional="defined(_WIN32) || defined(_WIN64)")
033public class Kernel32 {
034    
035    private static final Library LIBRARY = new Library("jansi", Kernel32.class);    
036        static {
037        LIBRARY.load();
038        init();
039        }
040
041    @JniMethod(flags={CONSTANT_INITIALIZER})
042    private static final native void init();
043
044    @JniField(flags={CONSTANT})
045    public static short FOREGROUND_BLUE;
046    @JniField(flags={CONSTANT})
047    public static short FOREGROUND_GREEN;
048    @JniField(flags={CONSTANT})
049    public static short FOREGROUND_RED;
050    @JniField(flags={CONSTANT})
051    public static short FOREGROUND_INTENSITY;
052    @JniField(flags={CONSTANT})
053    public static short BACKGROUND_BLUE;
054    @JniField(flags={CONSTANT})
055    public static short BACKGROUND_GREEN;
056    @JniField(flags={CONSTANT})
057    public static short BACKGROUND_RED;
058    @JniField(flags={CONSTANT})
059    public static short BACKGROUND_INTENSITY;
060    @JniField(flags={CONSTANT})
061    public static short COMMON_LVB_LEADING_BYTE;
062    @JniField(flags={CONSTANT})
063    public static short COMMON_LVB_TRAILING_BYTE;
064    @JniField(flags={CONSTANT})
065    public static short COMMON_LVB_GRID_HORIZONTAL;
066    @JniField(flags={CONSTANT})
067    public static short COMMON_LVB_GRID_LVERTICAL;
068    @JniField(flags={CONSTANT})
069    public static short COMMON_LVB_GRID_RVERTICAL;
070    @JniField(flags={CONSTANT})
071    public static short COMMON_LVB_REVERSE_VIDEO;
072    @JniField(flags={CONSTANT})
073    public static short COMMON_LVB_UNDERSCORE;    
074    @JniField(flags={CONSTANT})
075    public static int FORMAT_MESSAGE_FROM_SYSTEM;
076    @JniField(flags={CONSTANT})
077    public static int STD_INPUT_HANDLE;
078    @JniField(flags={CONSTANT})
079    public static int STD_OUTPUT_HANDLE;
080    @JniField(flags={CONSTANT})
081    public static int STD_ERROR_HANDLE;
082    @JniField(flags={CONSTANT})
083    public static int INVALID_HANDLE_VALUE;
084    
085
086    @JniMethod(cast="void *")
087    public static final native long malloc(
088            @JniArg(cast="size_t") long size);
089
090    public static final native void free(
091            @JniArg(cast="void *") long ptr);
092
093//    public static final native void memmove (
094//            @JniArg(cast="void *") long dest, 
095//            @JniArg(cast="const void *") long src, 
096//            @JniArg(cast="size_t") long size);
097//
098//    public static final native void memmove (
099//            @JniArg(cast="void *") long dest, 
100//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) byte[] src, 
101//            @JniArg(cast="size_t") long size);
102//
103//    public static final native void memmove (
104//            @JniArg(cast="void *") long dest, 
105//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) char[] src, 
106//            @JniArg(cast="size_t") long size);
107//
108//    public static final native void memmove (
109//            @JniArg(cast="void *") long dest, 
110//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  short[] src, 
111//            @JniArg(cast="size_t") long size);
112//
113//    public static final native void memmove (
114//            @JniArg(cast="void *") long dest, 
115//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  int[] src, 
116//            @JniArg(cast="size_t") long size);
117//
118//    public static final native void memmove (
119//            @JniArg(cast="void *") long dest, 
120//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}, pointer=FALSE) long[] src, 
121//            @JniArg(cast="size_t") long size);
122//
123//    public static final native void memmove (
124//            @JniArg(cast="void *") long dest, 
125//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) float[] src, 
126//            @JniArg(cast="size_t") long size);
127//
128//    public static final native void memmove (
129//            @JniArg(cast="void *") long dest, 
130//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) double[] src, 
131//            @JniArg(cast="size_t") long size);
132//
133//    
134//    
135//    public static final native void memmove (
136//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) byte[] dest, 
137//            @JniArg(cast="const void *") long src, 
138//            @JniArg(cast="size_t") long size);
139//
140//    public static final native void memmove (
141//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) char[] dest, 
142//            @JniArg(cast="const void *") long src, 
143//            @JniArg(cast="size_t") long size);
144//
145//    public static final native void memmove (
146//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) short[] dest, 
147//            @JniArg(cast="const void *") long src, 
148//            @JniArg(cast="size_t") long size);
149//
150//    public static final native void memmove (
151//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) int[] dest, 
152//            @JniArg(cast="const void *") long src, 
153//            @JniArg(cast="size_t") long size);
154//
155//    public static final native void memmove (
156//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}, pointer=FALSE) long[] dest, 
157//            @JniArg(cast="const void *") long src, 
158//            @JniArg(cast="size_t") long size);
159//    
160//    public static final native void memmove (
161//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) float[] dest, 
162//            @JniArg(cast="const void *") long src, 
163//            @JniArg(cast="size_t") long size);
164//
165//    public static final native void memmove (
166//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) double[] dest, 
167//            @JniArg(cast="const void *") long src, 
168//            @JniArg(cast="size_t") long size);
169//
170//    public static final native void memmove (
171//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) byte[] dest, 
172//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  char[] src, 
173//            @JniArg(cast="size_t") long size);
174//
175//    public static final native void memmove (
176//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) int[] dest, 
177//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) byte[] src, 
178//            @JniArg(cast="size_t") long size);
179//
180//    @JniMethod(cast="void *")
181//    public static final native long memset (
182//            @JniArg(cast="void *") long buffer, 
183//            int c, 
184//            @JniArg(cast="size_t") long num);
185//    
186//    public static final native int strlen(
187//            @JniArg(cast="char *")long s);
188//    
189//    public static final native void memmove (
190//            @JniArg(cast="void *") long dest, 
191//            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) foo src, 
192//            @JniArg(cast="size_t") long size);
193//    
194//    public static final native void memmove (
195//            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) foo dest, 
196//            @JniArg(cast="const void *") long src, 
197//            @JniArg(cast="size_t") long size);
198    
199    /**
200     * http://msdn.microsoft.com/en-us/library/ms686311%28VS.85%29.aspx
201     */
202    @JniClass(flags={STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
203    static public class SMALL_RECT {
204        static {
205            LIBRARY.load();
206            init();
207        }
208        
209        @JniMethod(flags={CONSTANT_INITIALIZER})
210        private static final native void init();
211        @JniField(flags={CONSTANT}, accessor="sizeof(SMALL_RECT)")
212        public static int SIZEOF;
213
214        @JniField(accessor="Left")
215        public short left;
216        @JniField(accessor="Top")
217        public short top;
218        @JniField(accessor="Right")
219        public short right;
220        @JniField(accessor="Bottom")
221        public short bottom;
222        
223        public short width() {
224            return (short) (right-left);
225        }
226        public short height() {
227            return (short) (bottom-top);
228        }
229        public SMALL_RECT copy() {
230            SMALL_RECT rc = new SMALL_RECT();
231            rc.left = left;
232            rc.top = top;
233            rc.right = right;
234            rc.bottom = bottom;
235            return rc;
236        }
237    }
238
239    /**
240     * see http://msdn.microsoft.com/en-us/library/ms686047%28VS.85%29.aspx
241     * @param consoleOutput
242     * @param attributes
243     * @return
244     */
245    public static final native int SetConsoleTextAttribute(
246            @JniArg(cast="HANDLE")long consoleOutput, 
247            short attributes);
248
249    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
250    public static class COORD {
251
252        static {
253            LIBRARY.load();
254            init();
255        }
256        
257        @JniMethod(flags={CONSTANT_INITIALIZER})
258        private static final native void init();
259        @JniField(flags={CONSTANT}, accessor="sizeof(COORD)")
260        public static int SIZEOF;
261
262        @JniField(accessor="X")
263        public short x;
264        @JniField(accessor="Y")
265        public short y;
266        
267        public COORD copy() {
268                COORD rc = new COORD();
269                rc.x = x;
270                rc.y = y;
271                return rc;
272        }
273    }
274    
275    /**
276     * http://msdn.microsoft.com/en-us/library/ms682093%28VS.85%29.aspx
277     */
278    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
279    public static class CONSOLE_SCREEN_BUFFER_INFO { 
280        
281        static {
282            LIBRARY.load();
283            init();
284        }
285        
286        @JniMethod(flags={CONSTANT_INITIALIZER})
287        private static final native void init();
288        @JniField(flags={CONSTANT}, accessor="sizeof(CONSOLE_SCREEN_BUFFER_INFO)")
289        public static int SIZEOF;
290
291        @JniField(accessor="dwSize")
292        public COORD      size = new COORD();
293        @JniField(accessor="dwCursorPosition")
294        public COORD      cursorPosition = new COORD();
295        @JniField(accessor="wAttributes")
296        public short      attributes;
297        @JniField(accessor="srWindow")
298        public SMALL_RECT window = new SMALL_RECT();
299        @JniField(accessor="dwMaximumWindowSize")
300        public COORD      maximumWindowSize = new COORD();
301        
302        public int windowWidth() {
303            return window.width() + 1;
304        }
305        
306        public int windowHeight() {
307            return window.height() + 1;
308        }
309    }
310
311
312    // DWORD WINAPI WaitForSingleObject(
313    //  _In_ HANDLE hHandle,
314    //  _In_ DWORD  dwMilliseconds
315    // );
316    public static final native int WaitForSingleObject(@JniArg(cast="HANDLE")long hHandle, int dwMilliseconds);
317
318    /**
319     * see: http://msdn.microsoft.com/en-us/library/ms724211%28VS.85%29.aspx
320     * 
321     * @param handle
322     * @return
323     */
324    public static final native int CloseHandle(@JniArg(cast="HANDLE")long handle);
325
326    
327    /**
328     * see: http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx
329     * 
330     * @return
331     */
332    public static final native int GetLastError();
333
334    /**
335     * 
336     * @param flags
337     * @param source
338     * @param messageId
339     * @param languageId
340     * @param buffer
341     * @param size
342     * @param args
343     * @return
344     */
345    public static final native int FormatMessageW(
346            int flags, 
347            @JniArg(cast="void *")long  source, 
348            int messageId,
349            int languageId, 
350            @JniArg(cast="void *", flags={NO_IN, CRITICAL})byte[] buffer, 
351            int size,
352            @JniArg(cast="void *", flags={NO_IN, CRITICAL, SENTINEL})long[] args
353            );
354    
355    
356    /**
357     * See: http://msdn.microsoft.com/en-us/library/ms683171%28VS.85%29.aspx
358     * @param consoleOutput
359     * @param consoleScreenBufferInfo
360     * @return
361     */
362    public static final native int GetConsoleScreenBufferInfo(
363            @JniArg(cast="HANDLE", flags={POINTER_ARG})long consoleOutput, 
364            @JniArg(flags={NO_IN}) CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo);
365    
366    /**
367     * see: http://msdn.microsoft.com/en-us/library/ms683231%28VS.85%29.aspx
368     * @param stdHandle
369     * @return
370     */
371    @JniMethod(cast="HANDLE", flags={POINTER_RETURN})
372    public static final native long GetStdHandle(int stdHandle);
373
374    /**
375     * http://msdn.microsoft.com/en-us/library/ms686025%28VS.85%29.aspx
376     * @param consoleOutput
377     * @param cursorPosition
378     * @return
379     */
380    public static final native int SetConsoleCursorPosition(
381            @JniArg(cast="HANDLE", flags={POINTER_ARG})long consoleOutput, 
382            @JniArg(flags={BY_VALUE,NO_OUT}) COORD cursorPosition);
383
384    /**
385     * see: http://msdn.microsoft.com/en-us/library/ms682663%28VS.85%29.aspx
386     * 
387     * @param consoleOutput
388     * @param character
389     * @param length
390     * @param writeCoord
391     * @param numberOfCharsWritten
392     * @return
393     */
394    public static final native int FillConsoleOutputCharacterW(
395            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long consoleOutput, 
396            char character, 
397            int length, 
398            @JniArg(flags={BY_VALUE,NO_OUT}) COORD writeCoord,
399            @JniArg(flags={NO_IN}) int[] numberOfCharsWritten);
400
401    /**
402     * see: https://msdn.microsoft.com/en-us/library/ms682662%28VS.85%29.aspx
403     *
404     * @param consoleOutput
405     * @param attribute
406     * @param length
407     * @param writeCoord
408     * @param numberOfAttrsWritten
409     * @return
410     */
411    public static final native int FillConsoleOutputAttribute(
412            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long consoleOutput,
413            short attribute,
414            int length,
415            @JniArg(flags={BY_VALUE,NO_OUT}) COORD writeCoord,
416            @JniArg(flags={NO_IN}) int[] numberOfAttrsWritten);
417
418    /**
419     * see: http://msdn.microsoft.com/en-us/library/ms687401(v=VS.85).aspx
420     *
421     * @param consoleOutput
422     * @param buffer
423     * @param numberOfCharsToWrite
424     * @param numberOfCharsWritten
425     * @param reserved must be null
426     * @return
427     */
428    public static final native int WriteConsoleW(
429            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long consoleOutput,
430            @JniArg(flags={NO_OUT}) char[] buffer,
431            int numberOfCharsToWrite,
432            @JniArg(flags={NO_IN}) int[] numberOfCharsWritten,
433            @JniArg(cast="LPVOID", flags={POINTER_ARG})long reserved);
434
435    /**
436     * see: http://msdn.microsoft.com/en-us/library/ms683167%28VS.85%29.aspx
437     * @param handle
438     * @param mode
439     * @return
440     */
441    public static final native int GetConsoleMode(
442            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle,
443            @JniArg(flags={NO_IN}) int[] mode);
444    
445    /**
446     * see: http://msdn.microsoft.com/en-us/library/ms686033%28VS.85%29.aspx
447     * @param handle
448     * @param mode
449     * @return
450     */
451    public static final native int SetConsoleMode(
452            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle, 
453            int mode);
454
455    /**
456     * see: http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx
457     * @return
458     */
459    public static final native int _getch();
460    
461
462    /**
463     * see: http://msdn.microsoft.com/en-us/library/ms686050%28VS.85%29.aspx
464     * @param title
465     * @return 0 if title was set successfully
466     */
467    public static final native int SetConsoleTitle(
468               @JniArg(flags={UNICODE}) String title);    
469
470
471    /**
472     * see: http://msdn.microsoft.com/en-us/library/ms683169(v=VS.85).aspx
473     * @return the current output code page
474     */
475    public static final native int GetConsoleOutputCP();
476
477    /**
478     * see: http://msdn.microsoft.com/en-us/library/ms686036(v=VS.85).aspx
479     * @param codePageID
480     * @return non 0 if code page was set
481     */
482    public static final native int SetConsoleOutputCP(int codePageID);
483
484    /**
485     * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682013(v=vs.85).aspx
486     */
487    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional = "defined(_WIN32) || defined(_WIN64)")
488    public static class CHAR_INFO {
489
490        static {
491            LIBRARY.load();
492            init();
493        }
494
495        @JniMethod(flags={CONSTANT_INITIALIZER})
496        private static final native void init();
497        @JniField(flags={CONSTANT}, accessor="sizeof(CHAR_INFO)")
498        public static int SIZEOF;
499
500        @JniField(accessor = "Attributes")
501        public short attributes;
502        @JniField(accessor="Char.UnicodeChar")
503        public char unicodeChar;
504    }
505
506    /**
507     * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685107(v=vs.85).aspx
508     */
509    public static final native int ScrollConsoleScreenBuffer(
510            @JniArg(cast="HANDLE", flags={POINTER_ARG})long consoleOutput,
511            @JniArg(flags={NO_OUT}) SMALL_RECT scrollRectangle,
512            @JniArg(flags={NO_OUT}) SMALL_RECT clipRectangle,
513            @JniArg(flags={BY_VALUE, NO_OUT}) COORD destinationOrigin,
514            @JniArg(flags={NO_OUT}) CHAR_INFO fill);
515
516    /**
517     * see: http://msdn.microsoft.com/en-us/library/ms684166(v=VS.85).aspx
518     */
519    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
520    public static class KEY_EVENT_RECORD {
521
522        static {
523            LIBRARY.load();
524            init();
525        }
526
527        @JniMethod(flags={CONSTANT_INITIALIZER})
528        private static final native void init();
529        @JniField(flags={CONSTANT}, accessor="sizeof(KEY_EVENT_RECORD)")
530        public static int SIZEOF;
531        @JniField(flags={CONSTANT}, accessor="CAPSLOCK_ON")
532        public static int CAPSLOCK_ON;
533        @JniField(flags={CONSTANT}, accessor="NUMLOCK_ON")
534        public static int NUMLOCK_ON;
535        @JniField(flags={CONSTANT}, accessor="SCROLLLOCK_ON")
536        public static int SCROLLLOCK_ON;
537        @JniField(flags={CONSTANT}, accessor="ENHANCED_KEY")
538        public static int ENHANCED_KEY;
539        @JniField(flags={CONSTANT}, accessor="LEFT_ALT_PRESSED")
540        public static int LEFT_ALT_PRESSED;
541        @JniField(flags={CONSTANT}, accessor="LEFT_CTRL_PRESSED")
542        public static int LEFT_CTRL_PRESSED;
543        @JniField(flags={CONSTANT}, accessor="RIGHT_ALT_PRESSED")
544        public static int RIGHT_ALT_PRESSED;
545        @JniField(flags={CONSTANT}, accessor="RIGHT_CTRL_PRESSED")
546        public static int RIGHT_CTRL_PRESSED;
547        @JniField(flags={CONSTANT}, accessor="SHIFT_PRESSED")
548        public static int SHIFT_PRESSED;
549
550        @JniField(accessor="bKeyDown")
551        public boolean keyDown;
552        @JniField(accessor="wRepeatCount")
553        public short repeatCount;
554        @JniField(accessor="wVirtualKeyCode")
555        public short keyCode;
556        @JniField(accessor="wVirtualScanCode")
557        public short scanCode;
558        @JniField(accessor="uChar.UnicodeChar")
559        public char uchar;
560        @JniField(accessor="dwControlKeyState")
561        public int controlKeyState;
562
563        public String toString() {
564            return "KEY_EVENT_RECORD{" +
565                    "keyDown=" + keyDown +
566                    ", repeatCount=" + repeatCount +
567                    ", keyCode=" + keyCode +
568                    ", scanCode=" + scanCode +
569                    ", uchar=" + uchar +
570                    ", controlKeyState=" + controlKeyState +
571                    '}';
572        }
573    }
574
575    /**
576     * see: http://msdn.microsoft.com/en-us/library/ms684239(v=VS.85).aspx
577     */
578    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
579    public static class MOUSE_EVENT_RECORD {
580
581        static {
582            LIBRARY.load();
583            init();
584        }
585
586        @JniMethod(flags={CONSTANT_INITIALIZER})
587        private static final native void init();
588        @JniField(flags={CONSTANT}, accessor="sizeof(MOUSE_EVENT_RECORD)")
589        public static int SIZEOF;
590        @JniField(flags={CONSTANT}, accessor="FROM_LEFT_1ST_BUTTON_PRESSED")
591        public static int FROM_LEFT_1ST_BUTTON_PRESSED;
592        @JniField(flags={CONSTANT}, accessor="FROM_LEFT_2ND_BUTTON_PRESSED")
593        public static int FROM_LEFT_2ND_BUTTON_PRESSED;
594        @JniField(flags={CONSTANT}, accessor="FROM_LEFT_3RD_BUTTON_PRESSED")
595        public static int FROM_LEFT_3RD_BUTTON_PRESSED;
596        @JniField(flags={CONSTANT}, accessor="FROM_LEFT_4TH_BUTTON_PRESSED")
597        public static int FROM_LEFT_4TH_BUTTON_PRESSED;
598        @JniField(flags={CONSTANT}, accessor="RIGHTMOST_BUTTON_PRESSED")
599        public static int RIGHTMOST_BUTTON_PRESSED;
600
601        @JniField(flags={CONSTANT}, accessor="CAPSLOCK_ON")
602        public static int CAPSLOCK_ON;
603        @JniField(flags={CONSTANT}, accessor="NUMLOCK_ON")
604        public static int NUMLOCK_ON;
605        @JniField(flags={CONSTANT}, accessor="SCROLLLOCK_ON")
606        public static int SCROLLLOCK_ON;
607        @JniField(flags={CONSTANT}, accessor="ENHANCED_KEY")
608        public static int ENHANCED_KEY;
609        @JniField(flags={CONSTANT}, accessor="LEFT_ALT_PRESSED")
610        public static int LEFT_ALT_PRESSED;
611        @JniField(flags={CONSTANT}, accessor="LEFT_CTRL_PRESSED")
612        public static int LEFT_CTRL_PRESSED;
613        @JniField(flags={CONSTANT}, accessor="RIGHT_ALT_PRESSED")
614        public static int RIGHT_ALT_PRESSED;
615        @JniField(flags={CONSTANT}, accessor="RIGHT_CTRL_PRESSED")
616        public static int RIGHT_CTRL_PRESSED;
617        @JniField(flags={CONSTANT}, accessor="SHIFT_PRESSED")
618        public static int SHIFT_PRESSED;
619
620        @JniField(flags={CONSTANT}, accessor="DOUBLE_CLICK")
621        public static int DOUBLE_CLICK;
622        @JniField(flags={CONSTANT}, accessor="MOUSE_HWHEELED")
623        public static int MOUSE_HWHEELED;
624        @JniField(flags={CONSTANT}, accessor="MOUSE_MOVED")
625        public static int MOUSE_MOVED;
626        @JniField(flags={CONSTANT}, accessor="MOUSE_WHEELED")
627        public static int MOUSE_WHEELED;
628
629        @JniField(accessor="dwMousePosition")
630        public COORD mousePosition = new COORD();
631        @JniField(accessor="dwButtonState")
632        public int buttonState;
633        @JniField(accessor="dwControlKeyState")
634        public int controlKeyState;
635        @JniField(accessor="dwEventFlags")
636        public int eventFlags;
637
638        public String toString() {
639            return "MOUSE_EVENT_RECORD{" +
640                    "mousePosition=" + mousePosition +
641                    ", buttonState=" + buttonState +
642                    ", controlKeyState=" + controlKeyState +
643                    ", eventFlags=" + eventFlags +
644                    '}';
645        }
646    }
647
648    /**
649     * see: http://msdn.microsoft.com/en-us/library/ms687093(v=VS.85).aspx
650     */
651    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
652    public static class WINDOW_BUFFER_SIZE_RECORD {
653
654        static {
655            LIBRARY.load();
656            init();
657        }
658
659        @JniMethod(flags={CONSTANT_INITIALIZER})
660        private static final native void init();
661        @JniField(flags={CONSTANT}, accessor="sizeof(WINDOW_BUFFER_SIZE_RECORD)")
662        public static int SIZEOF;
663
664        @JniField(accessor="dwSize")
665        public COORD size = new COORD();
666
667        public String toString() {
668            return "WINDOW_BUFFER_SIZE_RECORD{size=" + size + '}';
669        }
670    }
671
672    /**
673     * see: http://msdn.microsoft.com/en-us/library/ms683149(v=VS.85).aspx
674     */
675    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
676    public static class FOCUS_EVENT_RECORD {
677        static {
678            LIBRARY.load();
679            init();
680        }
681        @JniMethod(flags={CONSTANT_INITIALIZER})
682        private static final native void init();
683        @JniField(flags={CONSTANT}, accessor="sizeof(WINDOW_BUFFER_SIZE_RECORD)")
684        public static int SIZEOF;
685        @JniField(accessor="bSetFocus")
686        public boolean setFocus;
687    }
688
689    /**
690     * see: http://msdn.microsoft.com/en-us/library/ms684213(v=VS.85).aspx
691     */
692    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
693    public static class MENU_EVENT_RECORD {
694        static {
695            LIBRARY.load();
696            init();
697        }
698        @JniMethod(flags={CONSTANT_INITIALIZER})
699        private static final native void init();
700        @JniField(flags={CONSTANT}, accessor="sizeof(MENU_EVENT_RECORD)")
701        public static int SIZEOF;
702        @JniField(accessor="dwCommandId")
703        public int commandId;
704    }
705
706    /**
707     * see: http://msdn.microsoft.com/en-us/library/ms683499(v=VS.85).aspx
708     */
709    @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
710    public static class INPUT_RECORD {
711
712        static {
713            LIBRARY.load();
714            init();
715        }
716
717        @JniMethod(flags={CONSTANT_INITIALIZER})
718        private static final native void init();
719        @JniField(flags={CONSTANT}, accessor="sizeof(INPUT_RECORD)")
720        public static int SIZEOF;
721        @JniField(flags={CONSTANT}, accessor="KEY_EVENT")
722        public static short KEY_EVENT;
723        @JniField(flags={CONSTANT}, accessor="MOUSE_EVENT")
724        public static short MOUSE_EVENT;
725        @JniField(flags={CONSTANT}, accessor="WINDOW_BUFFER_SIZE_EVENT")
726        public static short WINDOW_BUFFER_SIZE_EVENT;
727        @JniField(flags={CONSTANT}, accessor="FOCUS_EVENT")
728        public static short FOCUS_EVENT;
729        @JniField(flags={CONSTANT}, accessor="MENU_EVENT")
730        public static short MENU_EVENT;
731        @JniField(accessor="EventType")
732        public short eventType;
733        @JniField(accessor="Event.KeyEvent")
734        public KEY_EVENT_RECORD keyEvent = new KEY_EVENT_RECORD();
735        @JniField(accessor="Event.MouseEvent")
736        public MOUSE_EVENT_RECORD mouseEvent = new MOUSE_EVENT_RECORD();
737        @JniField(accessor="Event.WindowBufferSizeEvent")
738        public WINDOW_BUFFER_SIZE_RECORD windowBufferSizeEvent = new WINDOW_BUFFER_SIZE_RECORD();
739        @JniField(accessor="Event.MenuEvent")
740        public MENU_EVENT_RECORD menuEvent = new MENU_EVENT_RECORD();
741        @JniField(accessor="Event.FocusEvent")
742        public FOCUS_EVENT_RECORD focusEvent = new FOCUS_EVENT_RECORD();
743
744        public static final native void memmove (
745          @JniArg(cast="void *", flags={NO_IN, CRITICAL}) INPUT_RECORD dest,
746          @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) long src,
747          @JniArg(cast="size_t") long size);
748
749    }
750
751    /**
752     * see: http://msdn.microsoft.com/en-us/library/ms684961(v=VS.85).aspx
753     * @param handle
754     * @param length
755     * @param eventsCount
756     * @return
757     */
758    private static final native int ReadConsoleInputW(
759            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle,
760            @JniArg(cast="PINPUT_RECORD", flags={POINTER_ARG}) long inputRecord,
761            int length,
762            @JniArg(flags={NO_IN}) int[] eventsCount);
763
764    /**
765     * see: http://msdn.microsoft.com/en-us/library/ms684344(v=VS.85).aspx
766     * @param handle
767     * @param length
768     * @param eventsCount
769     * @return
770     */
771    private static final native int PeekConsoleInputW(
772            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle,
773            @JniArg(cast="PINPUT_RECORD", flags={POINTER_ARG}) long inputRecord,
774            int length,
775            @JniArg(flags={NO_IN}) int[] eventsCount);
776
777    /**
778     * see: http://msdn.microsoft.com/en-us/library/ms683207(v=VS.85).aspx
779     * @param handle
780     * @param numberOfEvents number of unread input records in the console's input buffer
781     * @return
782     */
783    public static final native int GetNumberOfConsoleInputEvents(
784            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle,
785            @JniArg(flags={NO_IN}) int[] numberOfEvents);
786
787    /**
788     * see: http://msdn.microsoft.com/en-us/library/ms683147(v=VS.85).aspx
789     * @param handle
790     * @return
791     */
792    public static final native int FlushConsoleInputBuffer(
793            @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle);
794
795    /**
796     * Return console input events.
797     *
798     * @param handle
799     * @param count requested number of events
800     * @return null on read errors
801     */
802    public static INPUT_RECORD[] readConsoleInputHelper(
803            long handle, int count, boolean peek) throws IOException {
804        int[] length = new int[1];
805        int res;
806        long inputRecordPtr = 0;
807        try {
808            inputRecordPtr = malloc(INPUT_RECORD.SIZEOF * count);
809            if (inputRecordPtr == 0) {
810                throw new IOException("cannot allocate memory with JNI");
811            }
812            res = peek ?
813                    PeekConsoleInputW(handle, inputRecordPtr, count, length)
814                    : ReadConsoleInputW(handle, inputRecordPtr, count, length);
815            if (res == 0) {
816                throw new IOException("ReadConsoleInputW failed");
817            }
818            if (length[0] <= 0) {
819                return new INPUT_RECORD[0];
820            }
821            INPUT_RECORD[] records = new INPUT_RECORD[length[0]];
822            for (int i = 0; i < records.length; i++) {
823                records[i] = new INPUT_RECORD();
824                INPUT_RECORD.memmove(records[i], PointerMath.add(inputRecordPtr, i*INPUT_RECORD.SIZEOF), INPUT_RECORD.SIZEOF);
825            }
826            return records;
827        } finally {
828            if (inputRecordPtr != 0) {
829                free(inputRecordPtr);
830            }
831        }
832    }
833
834    /**
835     * Return console input key events (discard other events).
836     *
837     * @param count requested number of events
838     * @return array possibly of size smaller then count
839     */
840    public static INPUT_RECORD[] readConsoleKeyInput(long handle, int count, boolean peek)
841            throws IOException {
842        while (true) {
843            // read events until we have keyboard events, the queue could be full
844            // of mouse events.
845            INPUT_RECORD[] evts = readConsoleInputHelper(handle, count, peek);
846            int keyEvtCount = 0;
847            for (INPUT_RECORD evt : evts) {
848                if (evt.eventType == INPUT_RECORD.KEY_EVENT) keyEvtCount++;
849            }
850            if (keyEvtCount > 0) {
851                INPUT_RECORD[] res = new INPUT_RECORD[keyEvtCount];
852                int i = 0;
853                for (INPUT_RECORD evt : evts) {
854                    if (evt.eventType == INPUT_RECORD.KEY_EVENT) {
855                        res[i++] = evt;
856                    }
857                }
858                return res;
859            }
860        }
861    }
862
863
864}