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