001    /**
002     * Copyright (C) 2009, Progress Software Corporation and/or its 
003     * subsidiaries or affiliates.  All rights reserved.
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.fusesource.jansi.internal;
018    
019    import org.fusesource.hawtjni.runtime.ClassFlag;
020    import org.fusesource.hawtjni.runtime.JniArg;
021    import org.fusesource.hawtjni.runtime.JniClass;
022    import org.fusesource.hawtjni.runtime.JniField;
023    import org.fusesource.hawtjni.runtime.JniMethod;
024    import org.fusesource.hawtjni.runtime.Library;
025    
026    import static org.fusesource.hawtjni.runtime.ArgFlag.*;
027    import static org.fusesource.hawtjni.runtime.ClassFlag.*;
028    import static org.fusesource.hawtjni.runtime.FieldFlag.*;
029    import static org.fusesource.hawtjni.runtime.MethodFlag.*;
030    
031    /**
032     * 
033     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
034     */
035    @JniClass(conditional="defined(_WIN32) || defined(_WIN64)")
036    public class Kernel32 {
037        
038        private static final Library LIBRARY = new Library("jansi", Kernel32.class);    
039            static {
040            LIBRARY.load();
041            init();
042            }
043    
044        @JniMethod(flags={CONSTANT_INITIALIZER})
045        private static final native void init();
046    
047        @JniField(flags={CONSTANT})
048        public static short FOREGROUND_BLUE;
049        @JniField(flags={CONSTANT})
050        public static short FOREGROUND_GREEN;
051        @JniField(flags={CONSTANT})
052        public static short FOREGROUND_RED;
053        @JniField(flags={CONSTANT})
054        public static short FOREGROUND_INTENSITY;
055        @JniField(flags={CONSTANT})
056        public static short BACKGROUND_BLUE;
057        @JniField(flags={CONSTANT})
058        public static short BACKGROUND_GREEN;
059        @JniField(flags={CONSTANT})
060        public static short BACKGROUND_RED;
061        @JniField(flags={CONSTANT})
062        public static short BACKGROUND_INTENSITY;
063        @JniField(flags={CONSTANT})
064        public static short COMMON_LVB_LEADING_BYTE;
065        @JniField(flags={CONSTANT})
066        public static short COMMON_LVB_TRAILING_BYTE;
067        @JniField(flags={CONSTANT})
068        public static short COMMON_LVB_GRID_HORIZONTAL;
069        @JniField(flags={CONSTANT})
070        public static short COMMON_LVB_GRID_LVERTICAL;
071        @JniField(flags={CONSTANT})
072        public static short COMMON_LVB_GRID_RVERTICAL;
073        @JniField(flags={CONSTANT})
074        public static short COMMON_LVB_REVERSE_VIDEO;
075        @JniField(flags={CONSTANT})
076        public static short COMMON_LVB_UNDERSCORE;    
077        @JniField(flags={CONSTANT})
078        public static int FORMAT_MESSAGE_FROM_SYSTEM;
079        @JniField(flags={CONSTANT})
080        public static int STD_INPUT_HANDLE;
081        @JniField(flags={CONSTANT})
082        public static int STD_OUTPUT_HANDLE;
083        @JniField(flags={CONSTANT})
084        public static int STD_ERROR_HANDLE;
085        @JniField(flags={CONSTANT})
086        public static int INVALID_HANDLE_VALUE;
087        
088    
089        @JniMethod(cast="void *")
090        public static final native long malloc(
091                @JniArg(cast="size_t") long size);
092    
093        public static final native void free(
094                @JniArg(cast="void *") long ptr);
095    
096    //    public static final native void memmove (
097    //            @JniArg(cast="void *") long dest, 
098    //            @JniArg(cast="const void *") long src, 
099    //            @JniArg(cast="size_t") long size);
100    //
101    //    public static final native void memmove (
102    //            @JniArg(cast="void *") long dest, 
103    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) byte[] src, 
104    //            @JniArg(cast="size_t") long size);
105    //
106    //    public static final native void memmove (
107    //            @JniArg(cast="void *") long dest, 
108    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) char[] src, 
109    //            @JniArg(cast="size_t") long size);
110    //
111    //    public static final native void memmove (
112    //            @JniArg(cast="void *") long dest, 
113    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  short[] src, 
114    //            @JniArg(cast="size_t") long size);
115    //
116    //    public static final native void memmove (
117    //            @JniArg(cast="void *") long dest, 
118    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  int[] src, 
119    //            @JniArg(cast="size_t") long size);
120    //
121    //    public static final native void memmove (
122    //            @JniArg(cast="void *") long dest, 
123    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}, pointer=FALSE) long[] src, 
124    //            @JniArg(cast="size_t") long size);
125    //
126    //    public static final native void memmove (
127    //            @JniArg(cast="void *") long dest, 
128    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) float[] src, 
129    //            @JniArg(cast="size_t") long size);
130    //
131    //    public static final native void memmove (
132    //            @JniArg(cast="void *") long dest, 
133    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) double[] src, 
134    //            @JniArg(cast="size_t") long size);
135    //
136    //    
137    //    
138    //    public static final native void memmove (
139    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) byte[] dest, 
140    //            @JniArg(cast="const void *") long src, 
141    //            @JniArg(cast="size_t") long size);
142    //
143    //    public static final native void memmove (
144    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) char[] dest, 
145    //            @JniArg(cast="const void *") long src, 
146    //            @JniArg(cast="size_t") long size);
147    //
148    //    public static final native void memmove (
149    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) short[] dest, 
150    //            @JniArg(cast="const void *") long src, 
151    //            @JniArg(cast="size_t") long size);
152    //
153    //    public static final native void memmove (
154    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) int[] dest, 
155    //            @JniArg(cast="const void *") long src, 
156    //            @JniArg(cast="size_t") long size);
157    //
158    //    public static final native void memmove (
159    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}, pointer=FALSE) long[] dest, 
160    //            @JniArg(cast="const void *") long src, 
161    //            @JniArg(cast="size_t") long size);
162    //    
163    //    public static final native void memmove (
164    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) float[] dest, 
165    //            @JniArg(cast="const void *") long src, 
166    //            @JniArg(cast="size_t") long size);
167    //
168    //    public static final native void memmove (
169    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) double[] dest, 
170    //            @JniArg(cast="const void *") long src, 
171    //            @JniArg(cast="size_t") long size);
172    //
173    //    public static final native void memmove (
174    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) byte[] dest, 
175    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL})  char[] src, 
176    //            @JniArg(cast="size_t") long size);
177    //
178    //    public static final native void memmove (
179    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) int[] dest, 
180    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) byte[] src, 
181    //            @JniArg(cast="size_t") long size);
182    //
183    //    @JniMethod(cast="void *")
184    //    public static final native long memset (
185    //            @JniArg(cast="void *") long buffer, 
186    //            int c, 
187    //            @JniArg(cast="size_t") long num);
188    //    
189    //    public static final native int strlen(
190    //            @JniArg(cast="char *")long s);
191    //    
192    //    public static final native void memmove (
193    //            @JniArg(cast="void *") long dest, 
194    //            @JniArg(cast="const void *", flags={NO_OUT, CRITICAL}) foo src, 
195    //            @JniArg(cast="size_t") long size);
196    //    
197    //    public static final native void memmove (
198    //            @JniArg(cast="void *", flags={NO_IN, CRITICAL}) foo dest, 
199    //            @JniArg(cast="const void *") long src, 
200    //            @JniArg(cast="size_t") long size);
201        
202        /**
203         * http://msdn.microsoft.com/en-us/library/ms686311%28VS.85%29.aspx
204         */
205        @JniClass(flags={STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
206        static public class SMALL_RECT {
207            static {
208                LIBRARY.load();
209                init();
210            }
211            
212            @JniMethod(flags={CONSTANT_INITIALIZER})
213            private static final native void init();
214            @JniField(flags={CONSTANT}, accessor="sizeof(SMALL_RECT)")
215            public static int SIZEOF;
216    
217            @JniField(accessor="Left")
218            public short left;
219            @JniField(accessor="Top")
220            public short top;
221            @JniField(accessor="Right")
222            public short right;
223            @JniField(accessor="Bottom")
224            public short bottom;
225            
226            public short width() {
227                return (short) (right-left);
228            }
229            public short height() {
230                return (short) (bottom-top);
231            }
232        }    
233    
234        /**
235         * see http://msdn.microsoft.com/en-us/library/ms686047%28VS.85%29.aspx
236         * @param consoleOutput
237         * @param attributes
238         * @return
239         */
240        public static final native int SetConsoleTextAttribute(
241                @JniArg(cast="HANDLE")long consoleOutput, 
242                short attributes);
243    
244        @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
245        public static class COORD {
246    
247            static {
248                LIBRARY.load();
249                init();
250            }
251            
252            @JniMethod(flags={CONSTANT_INITIALIZER})
253            private static final native void init();
254            @JniField(flags={CONSTANT}, accessor="sizeof(COORD)")
255            public static int SIZEOF;
256    
257            @JniField(accessor="X")
258            public short x;
259            @JniField(accessor="Y")
260            public short y;
261            
262            public COORD copy() {
263                    COORD rc = new COORD();
264                    rc.x = x;
265                    rc.y = y;
266                    return rc;
267            }
268        }
269        
270        /**
271         * http://msdn.microsoft.com/en-us/library/ms682093%28VS.85%29.aspx
272         */
273        @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
274        public static class CONSOLE_SCREEN_BUFFER_INFO { 
275            
276            static {
277                LIBRARY.load();
278                init();
279            }
280            
281            @JniMethod(flags={CONSTANT_INITIALIZER})
282            private static final native void init();
283            @JniField(flags={CONSTANT}, accessor="sizeof(CONSOLE_SCREEN_BUFFER_INFO)")
284            public static int SIZEOF;
285    
286            @JniField(accessor="dwSize")
287            public COORD      size = new COORD();
288            @JniField(accessor="dwCursorPosition")
289            public COORD      cursorPosition = new COORD();
290            @JniField(accessor="wAttributes")
291            public short      attributes;
292            @JniField(accessor="srWindow")
293            public SMALL_RECT window = new SMALL_RECT();
294            @JniField(accessor="dwMaximumWindowSize")
295            public COORD      maximumWindowSize = new COORD();
296            
297            public int windowWidth() {
298                return window.width() + 1;
299            }
300            
301            public int windowHeight() {
302                return window.height() + 1;
303            }
304        }
305        
306        
307        /**
308         * see: http://msdn.microsoft.com/en-us/library/ms724211%28VS.85%29.aspx
309         * 
310         * @param handle
311         * @return
312         */
313        public static final native int CloseHandle(@JniArg(cast="HANDLE")long handle);
314    
315        
316        /**
317         * see: http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx
318         * 
319         * @param handle
320         * @return
321         */
322        public static final native int GetLastError();
323    
324        /**
325         * 
326         * @param flags
327         * @param source
328         * @param messageId
329         * @param languageId
330         * @param buffer
331         * @param size
332         * @param arguments
333         * @return
334         */
335        public static final native int FormatMessageW(
336                int flags, 
337                @JniArg(cast="void *")long  source, 
338                int messageId,
339                int languageId, 
340                @JniArg(cast="void *", flags={NO_IN, CRITICAL})byte[] buffer, 
341                int size,
342                @JniArg(cast="void *", flags={NO_IN, CRITICAL, SENTINEL})long []args
343                );
344        
345        
346        /**
347         * See: http://msdn.microsoft.com/en-us/library/ms683171%28VS.85%29.aspx
348         * @param consoleOutput
349         * @param consoleScreenBufferInfo
350         * @return
351         */
352        public static final native int GetConsoleScreenBufferInfo(
353                @JniArg(cast="HANDLE", flags={POINTER_ARG})long consoleOutput, 
354                CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo);
355        
356        /**
357         * see: http://msdn.microsoft.com/en-us/library/ms683231%28VS.85%29.aspx
358         * @param stdHandle
359         * @return
360         */
361        @JniMethod(cast="HANDLE", flags={POINTER_RETURN})
362        public static final native long GetStdHandle(int stdHandle);
363    
364        /**
365         * http://msdn.microsoft.com/en-us/library/ms686025%28VS.85%29.aspx
366         * @param consoleOutput
367         * @param cursorPosition
368         * @return
369         */
370        public static final native int SetConsoleCursorPosition(
371                @JniArg(cast="HANDLE", flags={POINTER_ARG})long consoleOutput, 
372                @JniArg(flags={BY_VALUE}) COORD cursorPosition);
373    
374        /**
375         * see: http://msdn.microsoft.com/en-us/library/ms682663%28VS.85%29.aspx
376         * 
377         * @param consoleOutput
378         * @param character
379         * @param length
380         * @param dwWriteCoord
381         * @param numberOfCharsWritten
382         * @return
383         */
384        public static final native int FillConsoleOutputCharacterW(
385                @JniArg(cast="HANDLE", flags={POINTER_ARG}) long consoleOutput, 
386                char character, 
387                int length, 
388                @JniArg(flags={BY_VALUE}) COORD writeCoord, 
389                int[] numberOfCharsWritten);
390     
391       
392        /**
393         * see: http://msdn.microsoft.com/en-us/library/ms683167%28VS.85%29.aspx
394         * @param handle
395         * @param mode
396         * @return
397         */
398        public static final native int GetConsoleMode(
399                @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle, 
400                int[] mode);
401        
402        /**
403         * see: http://msdn.microsoft.com/en-us/library/ms686033%28VS.85%29.aspx
404         * @param handle
405         * @param mode
406         * @return
407         */
408        public static final native int SetConsoleMode(
409                @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle, 
410                int mode);
411    
412        /**
413         * see: http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx
414         * @return
415         */
416        public static final native int _getch();
417        
418    
419       /**
420        * see: http://msdn.microsoft.com/en-us/library/ms686050%28VS.85%29.aspx
421        * @param title
422        * @return 0 if title was set successfully
423        */
424       public static final native int SetConsoleTitle(
425                   @JniArg(flags={UNICODE}) String title);    
426    
427        /**
428         * see: http://msdn.microsoft.com/en-us/library/ms684166(v=VS.85).aspx
429         */
430        @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
431        public static class KEY_EVENT_RECORD {
432    
433            static {
434                LIBRARY.load();
435                init();
436            }
437    
438            @JniMethod(flags={CONSTANT_INITIALIZER})
439            private static final native void init();
440            @JniField(flags={CONSTANT}, accessor="sizeof(KEY_EVENT_RECORD)")
441            public static int SIZEOF;
442            @JniField(flags={CONSTANT}, accessor="CAPSLOCK_ON")
443            public static int CAPSLOCK_ON;
444            @JniField(flags={CONSTANT}, accessor="NUMLOCK_ON")
445            public static int NUMLOCK_ON;
446            @JniField(flags={CONSTANT}, accessor="SCROLLLOCK_ON")
447            public static int SCROLLLOCK_ON;
448            @JniField(flags={CONSTANT}, accessor="ENHANCED_KEY")
449            public static int ENHANCED_KEY;
450            @JniField(flags={CONSTANT}, accessor="LEFT_ALT_PRESSED")
451            public static int LEFT_ALT_PRESSED;
452            @JniField(flags={CONSTANT}, accessor="LEFT_CTRL_PRESSED")
453            public static int LEFT_CTRL_PRESSED;
454            @JniField(flags={CONSTANT}, accessor="RIGHT_ALT_PRESSED")
455            public static int RIGHT_ALT_PRESSED;
456            @JniField(flags={CONSTANT}, accessor="RIGHT_CTRL_PRESSED")
457            public static int RIGHT_CTRL_PRESSED;
458            @JniField(flags={CONSTANT}, accessor="SHIFT_PRESSED")
459            public static int SHIFT_PRESSED;
460    
461            @JniField(accessor="bKeyDown")
462            public boolean keyDown;
463            @JniField(accessor="wRepeatCount")
464            public short repeatCount;
465            @JniField(accessor="wVirtualKeyCode")
466            public short keyCode;
467            @JniField(accessor="wVirtualScanCode")
468            public short scanCode;
469            @JniField(accessor="uChar.UnicodeChar")
470            public char uchar;
471            @JniField(accessor="dwControlKeyState")
472            public int controlKeyState;
473    
474            public String toString() {
475                return "KEY_EVENT_RECORD{" +
476                        "keyDown=" + keyDown +
477                        ", repeatCount=" + repeatCount +
478                        ", keyCode=" + keyCode +
479                        ", scanCode=" + scanCode +
480                        ", uchar=" + uchar +
481                        ", controlKeyState=" + controlKeyState +
482                        '}';
483            }
484        }
485    
486        /**
487         * see: http://msdn.microsoft.com/en-us/library/ms683499(v=VS.85).aspx
488         */
489        @JniClass(flags={ClassFlag.STRUCT,TYPEDEF}, conditional="defined(_WIN32) || defined(_WIN64)")
490        public static class INPUT_RECORD {
491    
492            static {
493                LIBRARY.load();
494                init();
495            }
496    
497            @JniMethod(flags={CONSTANT_INITIALIZER})
498            private static final native void init();
499            @JniField(flags={CONSTANT}, accessor="sizeof(INPUT_RECORD)")
500            public static int SIZEOF;
501            @JniField(flags={CONSTANT}, accessor="KEY_EVENT")
502            public static short KEY_EVENT;
503    
504            @JniField(accessor="EventType")
505            public short eventType;
506            @JniField(accessor="Event.KeyEvent")
507            public KEY_EVENT_RECORD keyEvent = new KEY_EVENT_RECORD();
508        }
509    
510        /**
511         * see: http://msdn.microsoft.com/en-us/library/ms684961(v=VS.85).aspx
512         * @param handle
513         * @param length must be exactly 1
514         * @param eventsCount
515         * @return
516         */
517        private static final native int ReadConsoleInputW(
518                @JniArg(cast="HANDLE", flags={POINTER_ARG}) long handle,
519                INPUT_RECORD inputRecord,
520                int length, // must be one
521                int[] eventsCount);
522    
523        /**
524         * Return a key event record (discard other events until a key event is
525         * found)
526         * @param handle
527         * @return null on read errors
528         */
529        public static KEY_EVENT_RECORD readKeyEvent(
530                long handle) {
531            int[] count = new int[1];
532            INPUT_RECORD inputRecord = new INPUT_RECORD();
533            int loop = 0; // give up after some arbitrary threshold
534            int res;
535            while (loop < 1000) {
536                res = ReadConsoleInputW(handle, inputRecord, 1, count);
537                if (res != 0 && count[0] == 1) {
538                    if (inputRecord.eventType == INPUT_RECORD.KEY_EVENT) {
539                        return inputRecord.keyEvent;
540                    }
541                } else {
542                    return null;
543                }
544                loop++;
545            }
546            return null;
547        }
548    }