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 java.io.IOException; 019 020import org.fusesource.jansi.WindowsSupport; 021 022/** 023 * Interface to access Win32 base APIs. 024 * 025 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 026 * @author Guillaume Nodet 027 * @see JansiLoader 028 */ 029@SuppressWarnings("unused") 030public class Kernel32 { 031 032 static { 033 if (JansiLoader.initialize()) { 034 init(); 035 } 036 } 037 038 private static native void init(); 039 040 public static short FOREGROUND_BLUE; 041 public static short FOREGROUND_GREEN; 042 public static short FOREGROUND_RED; 043 public static short FOREGROUND_INTENSITY; 044 public static short BACKGROUND_BLUE; 045 public static short BACKGROUND_GREEN; 046 public static short BACKGROUND_RED; 047 public static short BACKGROUND_INTENSITY; 048 public static short COMMON_LVB_LEADING_BYTE; 049 public static short COMMON_LVB_TRAILING_BYTE; 050 public static short COMMON_LVB_GRID_HORIZONTAL; 051 public static short COMMON_LVB_GRID_LVERTICAL; 052 public static short COMMON_LVB_GRID_RVERTICAL; 053 public static short COMMON_LVB_REVERSE_VIDEO; 054 public static short COMMON_LVB_UNDERSCORE; 055 public static int FORMAT_MESSAGE_FROM_SYSTEM; 056 public static int STD_INPUT_HANDLE; 057 public static int STD_OUTPUT_HANDLE; 058 public static int STD_ERROR_HANDLE; 059 public static int INVALID_HANDLE_VALUE; 060 061 062 public static native long malloc(long size); 063 064 public static native void free(long ptr); 065 066 /** 067 * http://msdn.microsoft.com/en-us/library/ms686311%28VS.85%29.aspx 068 */ 069 static public class SMALL_RECT { 070 static { 071 JansiLoader.initialize(); 072 init(); 073 } 074 075 private static native void init(); 076 077 public static int SIZEOF; 078 079 public short left; 080 public short top; 081 public short right; 082 public short bottom; 083 084 public short width() { 085 return (short) (right - left); 086 } 087 088 public short height() { 089 return (short) (bottom - top); 090 } 091 092 public SMALL_RECT copy() { 093 SMALL_RECT rc = new SMALL_RECT(); 094 rc.left = left; 095 rc.top = top; 096 rc.right = right; 097 rc.bottom = bottom; 098 return rc; 099 } 100 } 101 102 /** 103 * see http://msdn.microsoft.com/en-us/library/ms686047%28VS.85%29.aspx 104 */ 105 public static native int SetConsoleTextAttribute( 106 long consoleOutput, 107 short attributes); 108 109 public static class COORD { 110 111 static { 112 JansiLoader.initialize(); 113 init(); 114 } 115 116 private static native void init(); 117 118 public static int SIZEOF; 119 120 public short x; 121 public short y; 122 123 public COORD copy() { 124 COORD rc = new COORD(); 125 rc.x = x; 126 rc.y = y; 127 return rc; 128 } 129 } 130 131 /** 132 * http://msdn.microsoft.com/en-us/library/ms682093%28VS.85%29.aspx 133 */ 134 public static class CONSOLE_SCREEN_BUFFER_INFO { 135 136 static { 137 JansiLoader.initialize(); 138 init(); 139 } 140 141 private static native void init(); 142 143 public static int SIZEOF; 144 145 public COORD size = new COORD(); 146 public COORD cursorPosition = new COORD(); 147 public short attributes; 148 public SMALL_RECT window = new SMALL_RECT(); 149 public COORD maximumWindowSize = new COORD(); 150 151 public int windowWidth() { 152 return window.width() + 1; 153 } 154 155 public int windowHeight() { 156 return window.height() + 1; 157 } 158 } 159 160 161 // DWORD WINAPI WaitForSingleObject( 162 // _In_ HANDLE hHandle, 163 // _In_ DWORD dwMilliseconds 164 // ); 165 public static native int WaitForSingleObject(long hHandle, int dwMilliseconds); 166 167 /** 168 * see: http://msdn.microsoft.com/en-us/library/ms724211%28VS.85%29.aspx 169 */ 170 public static native int CloseHandle(long handle); 171 172 173 /** 174 * see: http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx 175 */ 176 public static native int GetLastError(); 177 178 public static native int FormatMessageW( 179 int flags, 180 long source, 181 int messageId, 182 int languageId, 183 byte[] buffer, 184 int size, 185 long[] args 186 ); 187 188 189 /** 190 * See: http://msdn.microsoft.com/en-us/library/ms683171%28VS.85%29.aspx 191 */ 192 public static native int GetConsoleScreenBufferInfo( 193 long consoleOutput, 194 CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo); 195 196 /** 197 * see: http://msdn.microsoft.com/en-us/library/ms683231%28VS.85%29.aspx 198 */ 199 public static native long GetStdHandle(int stdHandle); 200 201 /** 202 * http://msdn.microsoft.com/en-us/library/ms686025%28VS.85%29.aspx 203 */ 204 public static native int SetConsoleCursorPosition( 205 long consoleOutput, 206 COORD cursorPosition); 207 208 /** 209 * see: http://msdn.microsoft.com/en-us/library/ms682663%28VS.85%29.aspx 210 */ 211 public static native int FillConsoleOutputCharacterW( 212 long consoleOutput, 213 char character, 214 int length, 215 COORD writeCoord, 216 int[] numberOfCharsWritten); 217 218 /** 219 * see: https://msdn.microsoft.com/en-us/library/ms682662%28VS.85%29.aspx 220 */ 221 public static native int FillConsoleOutputAttribute( 222 long consoleOutput, 223 short attribute, 224 int length, 225 COORD writeCoord, 226 int[] numberOfAttrsWritten); 227 228 /** 229 * see: http://msdn.microsoft.com/en-us/library/ms687401(v=VS.85).aspx 230 */ 231 public static native int WriteConsoleW( 232 long consoleOutput, 233 char[] buffer, 234 int numberOfCharsToWrite, 235 int[] numberOfCharsWritten, 236 long reserved); 237 238 /** 239 * see: http://msdn.microsoft.com/en-us/library/ms683167%28VS.85%29.aspx 240 */ 241 public static native int GetConsoleMode( 242 long handle, 243 int[] mode); 244 245 /** 246 * see: http://msdn.microsoft.com/en-us/library/ms686033%28VS.85%29.aspx 247 */ 248 public static native int SetConsoleMode( 249 long handle, 250 int mode); 251 252 /** 253 * see: http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx 254 */ 255 public static native int _getch(); 256 257 258 /** 259 * see: http://msdn.microsoft.com/en-us/library/ms686050%28VS.85%29.aspx 260 * 261 * @return 0 if title was set successfully 262 */ 263 public static native int SetConsoleTitle( 264 String title); 265 266 267 /** 268 * see: http://msdn.microsoft.com/en-us/library/ms683169(v=VS.85).aspx 269 * 270 * @return the current output code page 271 */ 272 public static native int GetConsoleOutputCP(); 273 274 /** 275 * see: http://msdn.microsoft.com/en-us/library/ms686036(v=VS.85).aspx 276 * 277 * @return non 0 if code page was set 278 */ 279 public static native int SetConsoleOutputCP(int codePageID); 280 281 /** 282 * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682013(v=vs.85).aspx 283 */ 284 public static class CHAR_INFO { 285 286 static { 287 JansiLoader.initialize(); 288 init(); 289 } 290 291 private static native void init(); 292 293 public static int SIZEOF; 294 295 public short attributes; 296 public char unicodeChar; 297 } 298 299 /** 300 * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685107(v=vs.85).aspx 301 */ 302 public static native int ScrollConsoleScreenBuffer( 303 long consoleOutput, 304 SMALL_RECT scrollRectangle, 305 SMALL_RECT clipRectangle, 306 COORD destinationOrigin, 307 CHAR_INFO fill); 308 309 /** 310 * see: http://msdn.microsoft.com/en-us/library/ms684166(v=VS.85).aspx 311 */ 312 public static class KEY_EVENT_RECORD { 313 314 static { 315 JansiLoader.initialize(); 316 init(); 317 } 318 319 private static native void init(); 320 321 public static int SIZEOF; 322 public static int CAPSLOCK_ON; 323 public static int NUMLOCK_ON; 324 public static int SCROLLLOCK_ON; 325 public static int ENHANCED_KEY; 326 public static int LEFT_ALT_PRESSED; 327 public static int LEFT_CTRL_PRESSED; 328 public static int RIGHT_ALT_PRESSED; 329 public static int RIGHT_CTRL_PRESSED; 330 public static int SHIFT_PRESSED; 331 332 public boolean keyDown; 333 public short repeatCount; 334 public short keyCode; 335 public short scanCode; 336 public char uchar; 337 public int controlKeyState; 338 339 public String toString() { 340 return "KEY_EVENT_RECORD{" + 341 "keyDown=" + keyDown + 342 ", repeatCount=" + repeatCount + 343 ", keyCode=" + keyCode + 344 ", scanCode=" + scanCode + 345 ", uchar=" + uchar + 346 ", controlKeyState=" + controlKeyState + 347 '}'; 348 } 349 } 350 351 /** 352 * see: http://msdn.microsoft.com/en-us/library/ms684239(v=VS.85).aspx 353 */ 354 public static class MOUSE_EVENT_RECORD { 355 356 static { 357 JansiLoader.initialize(); 358 init(); 359 } 360 361 private static native void init(); 362 363 public static int SIZEOF; 364 public static int FROM_LEFT_1ST_BUTTON_PRESSED; 365 public static int FROM_LEFT_2ND_BUTTON_PRESSED; 366 public static int FROM_LEFT_3RD_BUTTON_PRESSED; 367 public static int FROM_LEFT_4TH_BUTTON_PRESSED; 368 public static int RIGHTMOST_BUTTON_PRESSED; 369 370 public static int CAPSLOCK_ON; 371 public static int NUMLOCK_ON; 372 public static int SCROLLLOCK_ON; 373 public static int ENHANCED_KEY; 374 public static int LEFT_ALT_PRESSED; 375 public static int LEFT_CTRL_PRESSED; 376 public static int RIGHT_ALT_PRESSED; 377 public static int RIGHT_CTRL_PRESSED; 378 public static int SHIFT_PRESSED; 379 380 public static int DOUBLE_CLICK; 381 public static int MOUSE_HWHEELED; 382 public static int MOUSE_MOVED; 383 public static int MOUSE_WHEELED; 384 385 public COORD mousePosition = new COORD(); 386 public int buttonState; 387 public int controlKeyState; 388 public int eventFlags; 389 390 public String toString() { 391 return "MOUSE_EVENT_RECORD{" + 392 "mousePosition=" + mousePosition + 393 ", buttonState=" + buttonState + 394 ", controlKeyState=" + controlKeyState + 395 ", eventFlags=" + eventFlags + 396 '}'; 397 } 398 } 399 400 /** 401 * see: http://msdn.microsoft.com/en-us/library/ms687093(v=VS.85).aspx 402 */ 403 public static class WINDOW_BUFFER_SIZE_RECORD { 404 405 static { 406 JansiLoader.initialize(); 407 init(); 408 } 409 410 private static native void init(); 411 412 public static int SIZEOF; 413 414 public COORD size = new COORD(); 415 416 public String toString() { 417 return "WINDOW_BUFFER_SIZE_RECORD{size=" + size + '}'; 418 } 419 } 420 421 /** 422 * see: http://msdn.microsoft.com/en-us/library/ms683149(v=VS.85).aspx 423 */ 424 public static class FOCUS_EVENT_RECORD { 425 static { 426 JansiLoader.initialize(); 427 init(); 428 } 429 430 private static native void init(); 431 432 public static int SIZEOF; 433 public boolean setFocus; 434 } 435 436 /** 437 * see: http://msdn.microsoft.com/en-us/library/ms684213(v=VS.85).aspx 438 */ 439 public static class MENU_EVENT_RECORD { 440 static { 441 JansiLoader.initialize(); 442 init(); 443 } 444 445 private static native void init(); 446 447 public static int SIZEOF; 448 public int commandId; 449 } 450 451 /** 452 * see: http://msdn.microsoft.com/en-us/library/ms683499(v=VS.85).aspx 453 */ 454 public static class INPUT_RECORD { 455 456 static { 457 JansiLoader.initialize(); 458 init(); 459 } 460 461 private static native void init(); 462 463 public static int SIZEOF; 464 public static short KEY_EVENT; 465 public static short MOUSE_EVENT; 466 public static short WINDOW_BUFFER_SIZE_EVENT; 467 public static short FOCUS_EVENT; 468 public static short MENU_EVENT; 469 public short eventType; 470 public KEY_EVENT_RECORD keyEvent = new KEY_EVENT_RECORD(); 471 public MOUSE_EVENT_RECORD mouseEvent = new MOUSE_EVENT_RECORD(); 472 public WINDOW_BUFFER_SIZE_RECORD windowBufferSizeEvent = new WINDOW_BUFFER_SIZE_RECORD(); 473 public MENU_EVENT_RECORD menuEvent = new MENU_EVENT_RECORD(); 474 public FOCUS_EVENT_RECORD focusEvent = new FOCUS_EVENT_RECORD(); 475 476 public static native void memmove( 477 INPUT_RECORD dest, 478 long src, 479 long size); 480 481 } 482 483 /** 484 * see: http://msdn.microsoft.com/en-us/library/ms684961(v=VS.85).aspx 485 */ 486 private static native int ReadConsoleInputW( 487 long handle, 488 long inputRecord, 489 int length, 490 int[] eventsCount); 491 492 /** 493 * see: http://msdn.microsoft.com/en-us/library/ms684344(v=VS.85).aspx 494 */ 495 private static native int PeekConsoleInputW( 496 long handle, 497 long inputRecord, 498 int length, 499 int[] eventsCount); 500 501 /** 502 * see: http://msdn.microsoft.com/en-us/library/ms683207(v=VS.85).aspx 503 */ 504 public static native int GetNumberOfConsoleInputEvents( 505 long handle, 506 int[] numberOfEvents); 507 508 /** 509 * see: http://msdn.microsoft.com/en-us/library/ms683147(v=VS.85).aspx 510 */ 511 public static native int FlushConsoleInputBuffer( 512 long handle); 513 514 /** 515 * Return console input events. 516 */ 517 public static INPUT_RECORD[] readConsoleInputHelper( 518 long handle, int count, boolean peek) throws IOException { 519 int[] length = new int[1]; 520 int res; 521 long inputRecordPtr = 0; 522 try { 523 inputRecordPtr = malloc(INPUT_RECORD.SIZEOF * count); 524 if (inputRecordPtr == 0) { 525 throw new IOException("cannot allocate memory with JNI"); 526 } 527 res = peek ? 528 PeekConsoleInputW(handle, inputRecordPtr, count, length) 529 : ReadConsoleInputW(handle, inputRecordPtr, count, length); 530 if (res == 0) { 531 throw new IOException("ReadConsoleInputW failed: " + WindowsSupport.getLastErrorMessage()); 532 } 533 if (length[0] <= 0) { 534 return new INPUT_RECORD[0]; 535 } 536 INPUT_RECORD[] records = new INPUT_RECORD[length[0]]; 537 for (int i = 0; i < records.length; i++) { 538 records[i] = new INPUT_RECORD(); 539 INPUT_RECORD.memmove(records[i], inputRecordPtr + i * INPUT_RECORD.SIZEOF, INPUT_RECORD.SIZEOF); 540 } 541 return records; 542 } finally { 543 if (inputRecordPtr != 0) { 544 free(inputRecordPtr); 545 } 546 } 547 } 548 549 /** 550 * Return console input key events (discard other events). 551 * 552 * @param count requested number of events 553 * @return array possibly of size smaller then count 554 */ 555 public static INPUT_RECORD[] readConsoleKeyInput(long handle, int count, boolean peek) 556 throws IOException { 557 while (true) { 558 // read events until we have keyboard events, the queue could be full 559 // of mouse events. 560 INPUT_RECORD[] evts = readConsoleInputHelper(handle, count, peek); 561 int keyEvtCount = 0; 562 for (INPUT_RECORD evt : evts) { 563 if (evt.eventType == INPUT_RECORD.KEY_EVENT) keyEvtCount++; 564 } 565 if (keyEvtCount > 0) { 566 INPUT_RECORD[] res = new INPUT_RECORD[keyEvtCount]; 567 int i = 0; 568 for (INPUT_RECORD evt : evts) { 569 if (evt.eventType == INPUT_RECORD.KEY_EVENT) { 570 res[i++] = evt; 571 } 572 } 573 return res; 574 } 575 } 576 } 577 578 579}