1 /**
2  * @namespace   biewlib
3  * @file        biewlib/sysdep/ia32/win32/keyboard.c
4  * @brief       This file contains implementation of keyboard handles for Win32s.
5  * @version     -
6  * @remark      this source file is part of Binary vIEW project (BIEW).
7  *              The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8  *              All rights reserved. This software is redistributable under the
9  *              licence given in the file "Licence.en" ("Licence.ru" in russian
10  *              translation) distributed in the BIEW archive.
11  * @note        Requires POSIX compatible development system
12  *
13  * @author      Nickols_K
14  * @since       1999
15  * @note        Development, fixes and improvements
16  * @author      Alexander Lokhan'ko <alex@eunet.lt>
17  * @date        28.03.2000
18  * @note        fixing code for workaround of console input bug under Win9x
19  *              tested on Win95 PE, OSR2, Win98
20  * @author      Alexander Lokhan'ko <alex@eunet.lt>
21  * @date        04.04.2000
22  * @note        removed slight delay in win9x console bug workaround code
23  * @warning     May not work propertly under some Win32 releases
24  * @author      Sergey Oblomov <hoopoepg@mail.ru>
25  * @date        28.05.2003
26  * @note        reworked console's reader to enable clipboard pasting
27  *              through SysMenu->Edit->Paste facility of window.
28  * @warning     May not work propertly under some Win32 releases
29  * @bug         Under WinNT does not return correct values for some
30  *              combinations of keys (like CtrlBkSpace)
31  * @note        added mouse wheel support for Win2k+ (emit Up/Down key event)
32  * @warning     ONE WHEEL SUPPORTED ONLY :-/
33  * @bug         Some wheel processing freezing found
34  * @author      Andrew Golovnia
35  * @date        19.12.2003
36 **/
37 /* for cygwin - remove unnecessary includes */
38 #define _OLE_H
39 #define _OLE2_H
40 #include <windows.h>
41 #include <limits.h>
42 #include <string.h>
43 #include <stdlib.h>
44 
45 #include "biewlib/kbd_code.h"
46 #include "biewlib/biewlib.h"
47 
48 static int KB_Buff[64];
49 static unsigned char KB_freq = 0;
50 static int shiftkeys = 0;
51 
52 #ifndef MOUSE_WHEELED
53 #define MOUSE_WHEELED	4 /*Windows NT and Windows Me/98/95:  This value is not supported.*/
54 #endif
55 
56 HANDLE hIn;
57 tBool hInputTrigger = False;
58 extern OSVERSIONINFO win32_verinfo;
59 static int is_win9x;
60 extern void __FASTCALL__ win32_readNextMessage( void );
61 
62 static int __mou_nbtns;
63 
is_VKCtrl(int code)64 static int __FASTCALL__ is_VKCtrl(int code)
65 {
66   return code == VK_MENU ||
67          code == VK_CONTROL ||
68          code == VK_SHIFT;
69 }
70 
71 extern tAbsCoord win32_mx,win32_my;
72 extern int win32_mbuttons;
73 
win32_readNextMessage(void)74 void __FASTCALL__ win32_readNextMessage( void )
75 {
76   //DWORD total_nread,i;
77   int vkeycode,keycode;
78   INPUT_RECORD ir;
79   DWORD nread;
80   hInputTrigger=False;
81 
82   PeekConsoleInput( hIn, &ir, 1, &nread );
83   if( nread )
84   {
85     ReadConsoleInput(hIn,&ir,1,&nread);
86     //if(!nread) break; /* sometimes happen */
87     switch(ir.EventType)
88     {
89       case MOUSE_EVENT:
90       {
91         static int buttons = 0;
92         win32_mbuttons = ir.Event.MouseEvent.dwButtonState & 0xffff;
93         if( buttons != win32_mbuttons )
94         {
95     	    win32_mx = ir.Event.MouseEvent.dwMousePosition.X;
96             win32_my = ir.Event.MouseEvent.dwMousePosition.Y;
97             if(KB_freq < sizeof(KB_Buff)/sizeof(int)) KB_Buff[KB_freq++] = KE_MOUSE;
98             buttons = win32_mbuttons & 0xffff;
99         }
100         if( ir.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED )
101         {
102             int wheel = ( (int)ir.Event.MouseEvent.dwButtonState ) >> 16;
103             if( wheel < 0 ) KB_Buff[KB_freq++] = KE_DOWNARROW;
104             if( wheel > 0 ) KB_Buff[KB_freq++] = KE_UPARROW;
105         }
106       }
107       return;
108       case KEY_EVENT:
109       {
110         shiftkeys = ir.Event.KeyEvent.dwControlKeyState;
111         vkeycode = ir.Event.KeyEvent.wVirtualKeyCode;
112 
113         if( ir.Event.KeyEvent.wVirtualKeyCode == 27 && ir.Event.KeyEvent.wVirtualScanCode == 1 &&
114             !ir.Event.KeyEvent.uChar.AsciiChar )
115             ir.Event.KeyEvent.uChar.AsciiChar = ir.Event.KeyEvent.wVirtualKeyCode;
116 
117         if(is_VKCtrl(vkeycode))
118         {
119           if(KB_freq < sizeof(KB_Buff)/sizeof(int)) KB_Buff[KB_freq++] = KE_SHIFTKEYS;
120         }
121         else
122         {
123             if( vkeycode < ' ' )
124                 vkeycode = 0;
125             keycode = ((ir.Event.KeyEvent.wVirtualScanCode << 8) & 0xFF00) |
126                       (ir.Event.KeyEvent.uChar.AsciiChar & 0xFF);
127             if(shiftkeys & SHIFT_PRESSED) keycode |= ADD_SHIFT;
128             else
129                 if(shiftkeys & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) keycode |= ADD_CONTROL;
130                 else
131                     if(shiftkeys & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) keycode |= ADD_ALT;
132             if(keycode && ir.Event.KeyEvent.bKeyDown)
133                 {if(KB_freq < sizeof(KB_Buff)/sizeof(int)) KB_Buff[KB_freq++] = keycode;}
134             else
135               if(KB_freq < sizeof(KB_Buff)/sizeof(int)) KB_Buff[KB_freq++] = KE_SHIFTKEYS;
136         }
137       }
138       return;
139       default: break;
140     }
141 //    if(is_win9x && !is_read) ReadConsoleInput(hIn,&ir,1,&nread);
142   }
143   else if( win32_mbuttons )
144   {
145     if(KB_freq < sizeof(KB_Buff)/sizeof(int)) KB_Buff[KB_freq++] = KE_MOUSE;
146   }
147   else
148       Sleep( 1 );
149 }
150 
__init_keyboard(const char * user_cp)151 void __FASTCALL__ __init_keyboard( const char *user_cp )
152 {
153   hIn = GetStdHandle(STD_INPUT_HANDLE);
154   is_win9x = win32_verinfo.dwMajorVersion == 4 &&
155              win32_verinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;
156   if((__mou_nbtns = __init_mouse()) != INT_MAX)
157   {
158     __MsSetState(True);
159   }
160 }
161 
__term_keyboard(void)162 void __FASTCALL__ __term_keyboard( void )
163 {
164   if(__mou_nbtns != INT_MAX)
165   {
166     __MsSetState(False);
167     __term_mouse();
168   }
169 }
170 
__kbdTestKey(unsigned long flg)171 int __FASTCALL__ __kbdTestKey( unsigned long flg )
172 {
173   if(__MsGetBtns() && flg == KBD_NONSTOP_ON_MOUSE_PRESS) return KE_MOUSE;
174   if(hInputTrigger) win32_readNextMessage();
175   return KB_freq;
176 }
177 
__kbdGetShiftsKey(void)178 int __FASTCALL__ __kbdGetShiftsKey( void )
179 {
180   int ret;
181   ret = 0;
182   if(hInputTrigger) win32_readNextMessage();
183   if(shiftkeys & SHIFT_PRESSED) ret |= KS_SHIFT;
184   if((shiftkeys & LEFT_ALT_PRESSED) || (shiftkeys & RIGHT_ALT_PRESSED)) ret |= KS_ALT;
185   if((shiftkeys & LEFT_CTRL_PRESSED) || (shiftkeys & RIGHT_CTRL_PRESSED)) ret |= KS_CTRL;
186   if(shiftkeys & CAPSLOCK_ON) ret |= KS_CAPSLOCK;
187   if(shiftkeys & NUMLOCK_ON) ret |= KS_NUMLOCK;
188   if(shiftkeys & SCROLLLOCK_ON) ret |= KS_SCRLOCK;
189   return ret;
190 }
191 
__kbdGetKey(unsigned long flg)192 int __FASTCALL__ __kbdGetKey ( unsigned long flg )
193 {
194   int ret;
195   if(__MsGetBtns() && flg == KBD_NONSTOP_ON_MOUSE_PRESS) return KE_MOUSE;
196   while(!KB_freq) { /*__OsYield()*/; win32_readNextMessage(); }
197   ret = KB_Buff[0];
198   --KB_freq;
199   if(KB_freq) memmove(KB_Buff,&KB_Buff[1],KB_freq*sizeof(int));
200   return ret;
201 }
202