2001-11-19 00:33:36 +00:00
|
|
|
#include "CMSWindowsSecondaryScreen.h"
|
2001-11-25 18:32:41 +00:00
|
|
|
#include "CMSWindowsClipboard.h"
|
2001-11-19 00:33:36 +00:00
|
|
|
#include "CClient.h"
|
2001-11-25 18:32:41 +00:00
|
|
|
#include "CClipboard.h"
|
2001-11-19 00:33:36 +00:00
|
|
|
#include "CThread.h"
|
|
|
|
#include "CLog.h"
|
|
|
|
#include <assert.h>
|
2002-05-04 18:08:22 +00:00
|
|
|
#include <ctype.h>
|
2001-11-19 00:33:36 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// CMSWindowsSecondaryScreen
|
|
|
|
//
|
|
|
|
|
|
|
|
CMSWindowsSecondaryScreen::CMSWindowsSecondaryScreen() :
|
|
|
|
m_client(NULL),
|
2001-11-25 18:32:41 +00:00
|
|
|
m_window(NULL),
|
|
|
|
m_nextClipboardWindow(NULL)
|
2001-11-19 00:33:36 +00:00
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
CMSWindowsSecondaryScreen::~CMSWindowsSecondaryScreen()
|
|
|
|
{
|
|
|
|
assert(m_window == NULL);
|
|
|
|
}
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
static CString s_log;
|
|
|
|
static CString s_logMore;
|
2001-11-19 00:33:36 +00:00
|
|
|
static HWND s_debug = NULL;
|
|
|
|
static HWND s_debugLog = NULL;
|
|
|
|
static DWORD s_thread = 0;
|
|
|
|
static BOOL CALLBACK WINAPI debugProc(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (msg) {
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_INITDIALOG:
|
2001-11-19 00:33:36 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_CLOSE:
|
2001-11-19 00:33:36 +00:00
|
|
|
PostQuitMessage(0);
|
|
|
|
return TRUE;
|
2001-11-25 18:32:41 +00:00
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_APP:
|
2001-11-25 18:32:41 +00:00
|
|
|
if (!s_logMore.empty()) {
|
2002-05-04 18:08:22 +00:00
|
|
|
if (s_log.size() > 40000)
|
2001-11-25 18:32:41 +00:00
|
|
|
s_log = s_logMore;
|
|
|
|
else
|
|
|
|
s_log += s_logMore;
|
|
|
|
s_logMore = "";
|
|
|
|
SendMessage(s_debugLog, WM_SETTEXT, FALSE, (LPARAM)(LPCTSTR)s_log.c_str());
|
|
|
|
SendMessage(s_debugLog, EM_SETSEL, s_log.size(), s_log.size());
|
|
|
|
SendMessage(s_debugLog, EM_SCROLLCARET, 0, 0);
|
|
|
|
}
|
|
|
|
return TRUE;
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
static void debugOutput(const char* msg)
|
|
|
|
{
|
2001-11-25 18:32:41 +00:00
|
|
|
s_logMore += msg;
|
|
|
|
PostMessage(s_debug, WM_APP, 0, 0);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::run()
|
|
|
|
{
|
|
|
|
CLog::setOutputter(&debugOutput);
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "entering event loop"));
|
2001-11-19 00:33:36 +00:00
|
|
|
doRun();
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "exiting event loop"));
|
2001-11-19 00:33:36 +00:00
|
|
|
CLog::setOutputter(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::stop()
|
|
|
|
{
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "requesting event loop stop"));
|
2001-11-19 00:33:36 +00:00
|
|
|
doStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::open(CClient* client)
|
|
|
|
{
|
|
|
|
assert(m_client == NULL);
|
|
|
|
assert(client != NULL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "opening screen"));
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// set the client
|
|
|
|
m_client = client;
|
|
|
|
|
|
|
|
// open the display
|
|
|
|
openDisplay();
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// update key state
|
|
|
|
updateKeys();
|
|
|
|
updateModifiers();
|
|
|
|
|
|
|
|
// assume primary has all clipboards
|
|
|
|
for (ClipboardID id = 0; id < kClipboardEnd; ++id)
|
|
|
|
grabClipboard(id);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::close()
|
|
|
|
{
|
|
|
|
assert(m_client != NULL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "closing screen"));
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// close the display
|
|
|
|
closeDisplay();
|
|
|
|
|
|
|
|
// done with client
|
|
|
|
m_client = NULL;
|
|
|
|
}
|
|
|
|
|
2002-04-30 17:48:11 +00:00
|
|
|
void CMSWindowsSecondaryScreen::enter(
|
|
|
|
SInt32 x, SInt32 y, KeyModifierMask mask)
|
2001-11-19 00:33:36 +00:00
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
2002-04-30 17:48:11 +00:00
|
|
|
log((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
|
2001-11-25 18:32:41 +00:00
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// warp to requested location
|
|
|
|
SInt32 w, h;
|
|
|
|
getScreenSize(&w, &h);
|
|
|
|
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
|
|
|
(DWORD)((65535.99 * x) / (w - 1)),
|
|
|
|
(DWORD)((65535.99 * y) / (h - 1)),
|
|
|
|
0, 0);
|
|
|
|
|
|
|
|
// show cursor
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "show cursor"));
|
2001-11-19 00:33:36 +00:00
|
|
|
ShowWindow(m_window, SW_HIDE);
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// update our keyboard state to reflect the local state
|
|
|
|
updateKeys();
|
|
|
|
updateModifiers();
|
2002-04-30 17:48:11 +00:00
|
|
|
|
|
|
|
// toggle modifiers that don't match the desired state
|
|
|
|
if ((mask & KeyModifierCapsLock) != (m_mask & KeyModifierCapsLock)) {
|
|
|
|
toggleKey(VK_CAPITAL, KeyModifierCapsLock);
|
|
|
|
}
|
|
|
|
if ((mask & KeyModifierNumLock) != (m_mask & KeyModifierNumLock)) {
|
|
|
|
toggleKey(VK_NUMLOCK, KeyModifierNumLock);
|
|
|
|
}
|
|
|
|
if ((mask & KeyModifierScrollLock) != (m_mask & KeyModifierScrollLock)) {
|
|
|
|
toggleKey(VK_SCROLL, KeyModifierScrollLock);
|
|
|
|
}
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::leave()
|
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "leaving screen"));
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// move hider window under the mouse (rather than moving the mouse
|
|
|
|
// somewhere else on the screen)
|
|
|
|
POINT point;
|
|
|
|
GetCursorPos(&point);
|
|
|
|
MoveWindow(m_window, point.x, point.y, 1, 1, FALSE);
|
|
|
|
|
|
|
|
// raise and show the hider window. take activation.
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "hide cursor"));
|
2001-11-19 00:33:36 +00:00
|
|
|
ShowWindow(m_window, SW_SHOWNORMAL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
// if we think we own the clipboard but we don't then somebody
|
|
|
|
// grabbed the clipboard on this screen without us knowing.
|
|
|
|
// tell the server that this screen grabbed the clipboard.
|
|
|
|
//
|
|
|
|
// this works around bugs in the clipboard viewer chain.
|
|
|
|
// sometimes NT will simply never send WM_DRAWCLIPBOARD
|
|
|
|
// messages for no apparent reason and rebooting fixes the
|
|
|
|
// problem. since we don't want a broken clipboard until the
|
|
|
|
// next reboot we do this double check. clipboard ownership
|
|
|
|
// won't be reflected on other screens until we leave but at
|
|
|
|
// least the clipboard itself will work.
|
|
|
|
HWND clipboardOwner = GetClipboardOwner();
|
|
|
|
if (m_clipboardOwner != clipboardOwner) {
|
|
|
|
m_clipboardOwner = clipboardOwner;
|
|
|
|
if (m_clipboardOwner != m_window) {
|
2002-04-30 16:23:03 +00:00
|
|
|
m_client->onClipboardChanged(kClipboardClipboard);
|
|
|
|
m_client->onClipboardChanged(kClipboardSelection);
|
2001-11-25 18:32:41 +00:00
|
|
|
}
|
|
|
|
}
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::keyDown(
|
|
|
|
KeyID key, KeyModifierMask mask)
|
|
|
|
{
|
2002-04-30 16:23:03 +00:00
|
|
|
Keystrokes keys;
|
|
|
|
UINT virtualKey;
|
|
|
|
|
|
|
|
// get the sequence of keys to simulate key press and the final
|
|
|
|
// modifier state.
|
2002-05-04 18:08:22 +00:00
|
|
|
m_mask = mapKey(keys, virtualKey, key, mask, kPress);
|
2002-04-30 16:23:03 +00:00
|
|
|
if (keys.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// generate key events
|
2002-05-04 18:08:22 +00:00
|
|
|
doKeystrokes(keys, 1);
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// note that key is now down
|
|
|
|
m_keys[virtualKey] |= 0x80;
|
2002-05-05 19:38:09 +00:00
|
|
|
switch (virtualKey) {
|
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
m_keys[VK_SHIFT] |= 0x80;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
m_keys[VK_CONTROL] |= 0x80;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
m_keys[VK_MENU] |= 0x80;
|
|
|
|
break;
|
|
|
|
}
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::keyRepeat(
|
|
|
|
KeyID key, KeyModifierMask mask, SInt32 count)
|
|
|
|
{
|
2002-04-30 16:23:03 +00:00
|
|
|
Keystrokes keys;
|
|
|
|
UINT virtualKey;
|
|
|
|
|
2002-05-04 18:08:22 +00:00
|
|
|
// get the sequence of keys to simulate key repeat and the final
|
2002-04-30 16:23:03 +00:00
|
|
|
// modifier state.
|
2002-05-04 18:08:22 +00:00
|
|
|
m_mask = mapKey(keys, virtualKey, key, mask, kRepeat);
|
2002-04-30 16:23:03 +00:00
|
|
|
if (keys.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// generate key events
|
2002-05-04 18:08:22 +00:00
|
|
|
doKeystrokes(keys, count);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::keyUp(
|
|
|
|
KeyID key, KeyModifierMask mask)
|
|
|
|
{
|
2002-04-30 16:23:03 +00:00
|
|
|
Keystrokes keys;
|
|
|
|
UINT virtualKey;
|
|
|
|
|
|
|
|
// get the sequence of keys to simulate key release and the final
|
|
|
|
// modifier state.
|
2002-05-04 18:08:22 +00:00
|
|
|
m_mask = mapKey(keys, virtualKey, key, mask, kRelease);
|
2002-04-30 16:23:03 +00:00
|
|
|
if (keys.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// generate key events
|
2002-05-04 18:08:22 +00:00
|
|
|
doKeystrokes(keys, 1);
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// note that key is now up
|
|
|
|
m_keys[virtualKey] &= ~0x80;
|
2002-05-05 19:38:09 +00:00
|
|
|
switch (virtualKey) {
|
|
|
|
case VK_LSHIFT:
|
|
|
|
if ((m_keys[VK_RSHIFT] & 0x80) == 0) {
|
|
|
|
m_keys[VK_SHIFT] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_RSHIFT:
|
|
|
|
if ((m_keys[VK_LSHIFT] & 0x80) == 0) {
|
|
|
|
m_keys[VK_SHIFT] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LCONTROL:
|
|
|
|
if ((m_keys[VK_RCONTROL] & 0x80) == 0) {
|
|
|
|
m_keys[VK_CONTROL] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_RCONTROL:
|
|
|
|
if ((m_keys[VK_LCONTROL] & 0x80) == 0) {
|
|
|
|
m_keys[VK_CONTROL] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LMENU:
|
|
|
|
if ((m_keys[VK_RMENU] & 0x80) == 0) {
|
|
|
|
m_keys[VK_MENU] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_RMENU:
|
|
|
|
if ((m_keys[VK_LMENU] & 0x80) == 0) {
|
|
|
|
m_keys[VK_MENU] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
|
|
|
{
|
|
|
|
// map button id to button flag
|
2002-05-04 18:08:22 +00:00
|
|
|
DWORD flags = mapButton(button, true);
|
2001-11-19 00:33:36 +00:00
|
|
|
|
|
|
|
// send event
|
2002-04-30 16:23:03 +00:00
|
|
|
if (flags != 0)
|
|
|
|
mouse_event(flags, 0, 0, 0, 0);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
|
|
|
|
{
|
|
|
|
// map button id to button flag
|
2002-05-04 18:08:22 +00:00
|
|
|
DWORD flags = mapButton(button, false);
|
2001-11-19 00:33:36 +00:00
|
|
|
|
|
|
|
// send event
|
2002-04-30 16:23:03 +00:00
|
|
|
if (flags != 0)
|
|
|
|
mouse_event(flags, 0, 0, 0, 0);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
|
|
|
|
{
|
|
|
|
SInt32 w, h;
|
|
|
|
getScreenSize(&w, &h);
|
|
|
|
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
|
|
|
(SInt32)(65535.99 * x / (w - 1)),
|
|
|
|
(SInt32)(65535.99 * y / (h - 1)),
|
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
|
|
|
{
|
|
|
|
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
|
|
|
|
}
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
void CMSWindowsSecondaryScreen::setClipboard(
|
2002-04-30 16:23:03 +00:00
|
|
|
ClipboardID id, const IClipboard* src)
|
2001-11-25 18:32:41 +00:00
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
|
|
|
CMSWindowsClipboard dst(m_window);
|
|
|
|
CClipboard::copy(&dst, src);
|
|
|
|
}
|
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
void CMSWindowsSecondaryScreen::grabClipboard(ClipboardID id)
|
2001-11-25 18:32:41 +00:00
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
|
|
|
CMSWindowsClipboard clipboard(m_window);
|
2002-04-30 16:23:03 +00:00
|
|
|
if (clipboard.open(0)) {
|
2001-11-25 18:32:41 +00:00
|
|
|
clipboard.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
void CMSWindowsSecondaryScreen::getSize(
|
|
|
|
SInt32* width, SInt32* height) const
|
|
|
|
{
|
|
|
|
getScreenSize(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
SInt32 CMSWindowsSecondaryScreen::getJumpZoneSize() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
void CMSWindowsSecondaryScreen::getClipboard(
|
2002-04-30 16:23:03 +00:00
|
|
|
ClipboardID id, IClipboard* dst) const
|
2001-11-25 18:32:41 +00:00
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
|
|
|
CMSWindowsClipboard src(m_window);
|
|
|
|
CClipboard::copy(dst, &src);
|
|
|
|
}
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
#include "resource.h" // FIXME
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::onOpenDisplay()
|
|
|
|
{
|
|
|
|
assert(m_window == NULL);
|
|
|
|
|
|
|
|
// create debug dialog
|
|
|
|
s_thread = GetCurrentThreadId();;
|
|
|
|
s_debug = CreateDialog(getInstance(), MAKEINTRESOURCE(IDD_SYNERGY), NULL, &debugProc);
|
|
|
|
s_debugLog = ::GetDlgItem(s_debug, IDC_LOG);
|
|
|
|
CLog::setOutputter(&debugOutput);
|
|
|
|
ShowWindow(s_debug, SW_SHOWNORMAL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
// initialize clipboard owner to current owner. we don't want
|
|
|
|
// to take ownership of the clipboard just by starting up.
|
|
|
|
m_clipboardOwner = GetClipboardOwner();
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// create the cursor hiding window. this window is used to hide the
|
|
|
|
// cursor when it's not on the screen. the window is hidden as soon
|
|
|
|
// as the cursor enters the screen or the display's real cursor is
|
|
|
|
// moved.
|
|
|
|
m_window = CreateWindowEx(WS_EX_TOPMOST |
|
|
|
|
WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
|
|
|
|
(LPCTSTR)getClass(), "Synergy",
|
2001-11-25 18:32:41 +00:00
|
|
|
WS_POPUP,
|
2001-11-19 00:33:36 +00:00
|
|
|
0, 0, 1, 1, NULL, NULL,
|
|
|
|
getInstance(),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
// hide the cursor
|
|
|
|
leave();
|
2001-11-25 18:32:41 +00:00
|
|
|
|
|
|
|
// install our clipboard snooper
|
|
|
|
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::onCloseDisplay()
|
|
|
|
{
|
|
|
|
assert(m_window != NULL);
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
// remove clipboard snooper
|
|
|
|
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
|
|
|
m_nextClipboardWindow = NULL;
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
// destroy window
|
|
|
|
DestroyWindow(m_window);
|
|
|
|
m_window = NULL;
|
|
|
|
|
|
|
|
CLog::setOutputter(NULL);
|
|
|
|
DestroyWindow(s_debug);
|
|
|
|
s_debug = NULL;
|
|
|
|
s_thread = 0;
|
|
|
|
}
|
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
bool CMSWindowsSecondaryScreen::onPreTranslate(MSG* msg)
|
2001-11-19 00:33:36 +00:00
|
|
|
{
|
|
|
|
if (IsDialogMessage(s_debug, msg)) {
|
|
|
|
return true;
|
|
|
|
}
|
2001-11-25 18:32:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2001-11-19 00:33:36 +00:00
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
LRESULT CMSWindowsSecondaryScreen::onEvent(
|
|
|
|
HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (msg) {
|
2002-04-29 14:40:01 +00:00
|
|
|
// FIXME -- handle display changes
|
|
|
|
case WM_PAINT:
|
2001-11-25 18:32:41 +00:00
|
|
|
ValidateRect(hwnd, NULL);
|
|
|
|
return 0;
|
2001-11-19 00:33:36 +00:00
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_ACTIVATEAPP:
|
2001-11-25 18:32:41 +00:00
|
|
|
if (wParam == FALSE) {
|
2001-11-19 00:33:36 +00:00
|
|
|
// some other app activated. hide the hider window.
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_INFO "show cursor"));
|
2001-11-19 00:33:36 +00:00
|
|
|
ShowWindow(m_window, SW_HIDE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_DRAWCLIPBOARD:
|
2001-11-25 18:32:41 +00:00
|
|
|
log((CLOG_DEBUG "clipboard was taken"));
|
2001-11-19 00:33:36 +00:00
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
// first pass it on
|
|
|
|
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
2001-11-19 00:33:36 +00:00
|
|
|
|
2001-11-25 18:32:41 +00:00
|
|
|
// now notify client that somebody changed the clipboard (unless
|
|
|
|
// we're now the owner, in which case it's because we took
|
|
|
|
// ownership).
|
|
|
|
m_clipboardOwner = GetClipboardOwner();
|
|
|
|
if (m_clipboardOwner != m_window) {
|
2002-04-30 16:23:03 +00:00
|
|
|
m_client->onClipboardChanged(kClipboardClipboard);
|
|
|
|
m_client->onClipboardChanged(kClipboardSelection);
|
2001-11-25 18:32:41 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
2002-04-29 14:40:01 +00:00
|
|
|
case WM_CHANGECBCHAIN:
|
2001-11-25 18:32:41 +00:00
|
|
|
if (m_nextClipboardWindow == (HWND)wParam)
|
|
|
|
m_nextClipboardWindow = (HWND)lParam;
|
|
|
|
else
|
|
|
|
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
|
|
|
return 0;
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
2001-11-25 18:32:41 +00:00
|
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const UINT g_latin1[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin2[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin3[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin4[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin5[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin6[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin7[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin8[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_latin9[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_terminal[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const UINT g_function[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
2002-05-04 18:08:22 +00:00
|
|
|
/* 0x20 */ VK_TAB, 0, 0, 0, 0, 0, 0, 0,
|
2001-11-19 00:33:36 +00:00
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
/* XK_KP_Space to XK_KP_Equal */
|
|
|
|
static const UINT g_miscellany[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x08 */ VK_BACK, VK_TAB, /*0x100 +*/ VK_RETURN, VK_CLEAR, 0, VK_RETURN, 0, 0,
|
|
|
|
/* 0x10 */ 0, 0, 0, VK_PAUSE, VK_SCROLL, 0/*sys-req*/, 0, 0,
|
|
|
|
/* 0x18 */ 0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,
|
|
|
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x50 */ VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,
|
|
|
|
/* 0x54 */ VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
|
|
|
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x60 */ VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, VK_APPS,
|
|
|
|
/* 0x68 */ 0, 0, VK_HELP, VK_CANCEL, 0, 0, 0, 0,
|
|
|
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, VK_MODECHANGE, VK_NUMLOCK,
|
|
|
|
/* 0x80 */ VK_SPACE, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0x88 */ 0, VK_TAB, 0, 0, 0, VK_RETURN, 0, 0,
|
|
|
|
/* 0x90 */ 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,
|
|
|
|
/* 0x98 */ VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,
|
|
|
|
/* 0x9c */ VK_END, 0, VK_INSERT, VK_DELETE,
|
|
|
|
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xa8 */ 0, 0, VK_MULTIPLY, VK_ADD,
|
|
|
|
/* 0xac */ VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
|
|
|
|
/* 0xb0 */ VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
|
|
|
/* 0xb4 */ VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
|
|
|
/* 0xb8 */ VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0, VK_F1, VK_F2,
|
|
|
|
/* 0xc0 */ VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,
|
|
|
|
/* 0xc8 */ VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18,
|
|
|
|
/* 0xd0 */ VK_F19, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, 0, 0,
|
|
|
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
2002-05-05 19:38:09 +00:00
|
|
|
/* 0xe0 */ 0, VK_LSHIFT, VK_RSHIFT, VK_LCONTROL,
|
2001-11-19 00:33:36 +00:00
|
|
|
/* 0xe4 */ VK_RCONTROL, VK_CAPITAL, 0, VK_LWIN,
|
2002-05-05 19:38:09 +00:00
|
|
|
/* 0xe8 */ VK_RWIN, VK_LMENU, VK_RMENU, 0, 0, 0, 0, 0,
|
2001-11-19 00:33:36 +00:00
|
|
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, VK_DELETE
|
|
|
|
};
|
|
|
|
static const UINT* g_katakana = NULL;
|
|
|
|
static const UINT* g_arabic = NULL;
|
|
|
|
static const UINT* g_cyrillic = NULL;
|
|
|
|
static const UINT* g_greek = NULL;
|
|
|
|
static const UINT* g_technical = NULL;
|
|
|
|
static const UINT* g_special = NULL;
|
|
|
|
static const UINT* g_publishing = NULL;
|
|
|
|
static const UINT* g_apl = NULL;
|
|
|
|
static const UINT* g_hebrew = NULL;
|
|
|
|
static const UINT* g_thai = NULL;
|
|
|
|
static const UINT* g_korean = NULL;
|
|
|
|
static const UINT* g_armenian = NULL;
|
|
|
|
static const UINT* g_georgian = NULL;
|
|
|
|
static const UINT* g_azeri = NULL;
|
|
|
|
static const UINT* g_vietnamese = NULL;
|
|
|
|
static const UINT* g_currency = NULL;
|
|
|
|
static const UINT* g_mapTable[] =
|
|
|
|
{
|
|
|
|
/* 0x00 */ g_latin1, g_latin2, g_latin3, g_latin4,
|
|
|
|
/* 0x04 */ g_katakana, g_arabic, g_cyrillic, g_greek,
|
|
|
|
/* 0x08 */ g_technical, g_special, g_publishing, g_apl,
|
|
|
|
/* 0x0c */ g_hebrew, g_thai, g_korean, NULL,
|
|
|
|
/* 0x10 */ NULL, NULL, g_latin8, g_latin9,
|
|
|
|
/* 0x14 */ g_armenian, g_georgian, g_azeri, NULL,
|
|
|
|
/* 0x18 */ NULL, NULL, NULL, NULL, NULL, NULL, g_vietnamese, NULL,
|
|
|
|
/* 0x20 */ g_currency, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x28 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x30 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x38 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x40 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x48 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x50 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x58 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x60 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x68 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x70 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x78 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x80 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x88 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x90 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0x98 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xa0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xa8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xb0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xb8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xc0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xc8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xd0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xd8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xe0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xe8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xf0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xf8 */ NULL, NULL, NULL, NULL,
|
|
|
|
/* 0xfc */ NULL, g_terminal, g_function, g_miscellany
|
|
|
|
};
|
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
DWORD CMSWindowsSecondaryScreen::mapButton(
|
2002-05-04 18:08:22 +00:00
|
|
|
ButtonID button, bool press) const
|
2001-11-19 00:33:36 +00:00
|
|
|
{
|
2002-04-30 16:23:03 +00:00
|
|
|
// map button id to button flag
|
|
|
|
switch (button) {
|
|
|
|
case kButtonLeft:
|
2002-05-04 18:08:22 +00:00
|
|
|
return press ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
case kButtonMiddle:
|
2002-05-04 18:08:22 +00:00
|
|
|
return press ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
|
2001-11-19 00:33:36 +00:00
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
case kButtonRight:
|
2002-05-04 18:08:22 +00:00
|
|
|
return press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
|
|
|
Keystrokes& keys,
|
|
|
|
UINT& virtualKey,
|
|
|
|
KeyID id, KeyModifierMask mask,
|
2002-05-04 18:08:22 +00:00
|
|
|
EKeyAction action) const
|
2002-04-30 16:23:03 +00:00
|
|
|
{
|
2001-11-19 00:33:36 +00:00
|
|
|
// lookup the key table
|
2002-04-30 16:23:03 +00:00
|
|
|
const UInt32 mapID = ((id >> 8) & 0xff);
|
|
|
|
const UINT* map = g_mapTable[mapID];
|
2001-11-19 00:33:36 +00:00
|
|
|
if (map == NULL) {
|
2002-04-30 16:23:03 +00:00
|
|
|
// unknown key
|
|
|
|
return m_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
// look up virtual key for id. default output mask carries over
|
2002-05-05 19:38:09 +00:00
|
|
|
// the current toggle modifier states and includes desired shift,
|
|
|
|
// control, alt, and meta states.
|
2002-04-30 16:23:03 +00:00
|
|
|
const UInt32 code = (id & 0xff);
|
|
|
|
virtualKey = map[code];
|
|
|
|
KeyModifierMask outMask = (m_mask &
|
|
|
|
(KeyModifierCapsLock |
|
|
|
|
KeyModifierNumLock |
|
|
|
|
KeyModifierScrollLock));
|
2002-05-05 19:38:09 +00:00
|
|
|
outMask |= (mask &
|
|
|
|
(KeyModifierShift |
|
|
|
|
KeyModifierControl |
|
|
|
|
KeyModifierAlt |
|
|
|
|
KeyModifierMeta));
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "key id %d -> virtual key %d", id, virtualKey));
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// if not in map then ask system to convert ascii character
|
|
|
|
if (virtualKey == 0) {
|
|
|
|
if (mapID != 0) {
|
|
|
|
// not ascii
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "not ascii"));
|
2002-04-30 16:23:03 +00:00
|
|
|
return m_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
// translate. return no keys if unknown key.
|
|
|
|
SHORT vk = VkKeyScan(code);
|
|
|
|
if (vk == 0xffff) {
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "no virtual key for character %d", code));
|
2002-04-30 16:23:03 +00:00
|
|
|
return m_mask;
|
|
|
|
}
|
|
|
|
|
2002-05-05 19:38:09 +00:00
|
|
|
// use whatever shift state VkKeyScan says
|
|
|
|
// FIXME -- also for control and alt, but it's more difficult
|
|
|
|
// to determine if control and alt must be off or if it just
|
|
|
|
// doesn't matter.
|
|
|
|
outMask &= ~KeyModifierShift;
|
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
// convert system modifier mask to our mask
|
|
|
|
if (HIBYTE(vk) & 1)
|
|
|
|
outMask |= KeyModifierShift;
|
|
|
|
if (HIBYTE(vk) & 2)
|
|
|
|
outMask |= KeyModifierControl;
|
|
|
|
if (HIBYTE(vk) & 4)
|
|
|
|
outMask |= KeyModifierAlt;
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "character %d to virtual key %d mask 0x%04x", code, LOBYTE(vk), outMask));
|
|
|
|
|
|
|
|
// handle combination of caps-lock and shift. if caps-lock is
|
|
|
|
// off locally then use shift as necessary. if caps-lock is on
|
|
|
|
// locally then shift reverses its meaning (for keys that are
|
|
|
|
// subject to case conversion).
|
|
|
|
if ((m_mask & KeyModifierCapsLock) != 0) {
|
|
|
|
// caps-lock is on. note if shift is required.
|
|
|
|
log((CLOG_DEBUG2 "caps-lock is on"));
|
|
|
|
const bool needShift = ((outMask & KeyModifierShift) != 0);
|
|
|
|
|
|
|
|
// if needShift is true then see if the key is subject to
|
|
|
|
// case conversion. if it is then caps-lock and shift
|
|
|
|
// cancel out. if not then caps-lock is ignored and shift
|
|
|
|
// is required.
|
|
|
|
if (needShift) {
|
|
|
|
// FIXME -- there should be some system call to test
|
|
|
|
// if a key is subject to case conversion.
|
|
|
|
if (tolower(code) != toupper(code)) {
|
|
|
|
log((CLOG_DEBUG2 "turn off shift"));
|
|
|
|
outMask &= ~KeyModifierShift;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// get virtual key
|
|
|
|
virtualKey = LOBYTE(vk);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if in map then figure out correct modifier state
|
|
|
|
else {
|
|
|
|
// check numeric keypad. note that while KeyID distinguishes
|
|
|
|
// between the keypad movement keys (e.g. Home, left arrow),
|
|
|
|
// the virtual keys do not. however, the virtual keys do
|
|
|
|
// distinguish between keypad numbers and operators (e.g.
|
|
|
|
// add, multiply) and their main keyboard counterparts.
|
|
|
|
// therefore, we can ignore the num-lock state for movement
|
|
|
|
// virtual keys but not for numeric keys.
|
|
|
|
if (virtualKey >= VK_NUMPAD0 && virtualKey <= VK_DIVIDE) {
|
|
|
|
// set required shift state based on current numlock state
|
2002-05-04 18:08:22 +00:00
|
|
|
if ((outMask & KeyModifierNumLock) == 0) {
|
|
|
|
if ((m_mask & KeyModifierNumLock) == 0) {
|
|
|
|
log((CLOG_DEBUG2 "turn on num lock for keypad key"));
|
|
|
|
outMask |= KeyModifierNumLock;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
log((CLOG_DEBUG2 "turn on shift for keypad key"));
|
|
|
|
outMask |= KeyModifierShift;
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
|
2002-05-04 18:08:22 +00:00
|
|
|
// check for ISO_Left_Tab
|
|
|
|
else if (id == 0xfe20) {
|
|
|
|
outMask |= KeyModifierShift;
|
|
|
|
}
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// a list of modifier key info
|
|
|
|
class CModifierInfo {
|
|
|
|
public:
|
2002-05-05 19:38:09 +00:00
|
|
|
KeyModifierMask m_mask;
|
|
|
|
UINT m_virtualKey;
|
|
|
|
UINT m_virtualKey2;
|
|
|
|
bool m_isToggle;
|
2002-04-30 16:23:03 +00:00
|
|
|
};
|
|
|
|
static const CModifierInfo s_modifier[] = {
|
2002-05-05 19:38:09 +00:00
|
|
|
{ KeyModifierShift, VK_LSHIFT, VK_RSHIFT, false },
|
|
|
|
{ KeyModifierControl, VK_LCONTROL, VK_RCONTROL,false },
|
|
|
|
{ KeyModifierAlt, VK_LMENU, VK_RMENU, false },
|
|
|
|
{ KeyModifierMeta, VK_LWIN, VK_RWIN, false },
|
|
|
|
{ KeyModifierCapsLock, VK_CAPITAL, 0, true },
|
|
|
|
{ KeyModifierNumLock, VK_NUMLOCK, 0, true },
|
|
|
|
{ KeyModifierScrollLock, VK_SCROLL, 0, true }
|
2002-04-30 16:23:03 +00:00
|
|
|
};
|
|
|
|
static const unsigned int s_numModifiers =
|
|
|
|
sizeof(s_modifier) / sizeof(s_modifier[0]);
|
|
|
|
|
|
|
|
// note if the key is a modifier
|
|
|
|
unsigned int modifierIndex;
|
|
|
|
switch (virtualKey) {
|
|
|
|
case VK_SHIFT:
|
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
modifierIndex = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_CONTROL:
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
modifierIndex = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_MENU:
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
modifierIndex = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
modifierIndex = 3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_CAPITAL:
|
|
|
|
modifierIndex = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
modifierIndex = 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_SCROLL:
|
|
|
|
modifierIndex = 6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
modifierIndex = s_numModifiers;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
const bool isModifier = (modifierIndex != s_numModifiers);
|
|
|
|
|
|
|
|
// add the key events required to get to the modifier state
|
|
|
|
// necessary to generate an event yielding id. also save the
|
|
|
|
// key events required to restore the state. if the key is
|
|
|
|
// a modifier key then skip this because modifiers should not
|
|
|
|
// modify modifiers.
|
|
|
|
Keystrokes undo;
|
2002-05-04 18:08:22 +00:00
|
|
|
Keystroke keystroke;
|
2002-04-30 16:23:03 +00:00
|
|
|
if (outMask != m_mask && !isModifier) {
|
|
|
|
for (unsigned int i = 0; i < s_numModifiers; ++i) {
|
2002-05-05 19:38:09 +00:00
|
|
|
KeyModifierMask bit = s_modifier[i].m_mask;
|
2002-04-30 16:23:03 +00:00
|
|
|
if ((outMask & bit) != (m_mask & bit)) {
|
|
|
|
if ((outMask & bit) != 0) {
|
|
|
|
// modifier is not active but should be. if the
|
|
|
|
// modifier is a toggle then toggle it on with a
|
|
|
|
// press/release, otherwise activate it with a
|
|
|
|
// press.
|
2002-05-05 19:38:09 +00:00
|
|
|
keystroke.m_virtualKey = s_modifier[i].m_virtualKey;
|
2002-05-04 18:08:22 +00:00
|
|
|
keystroke.m_press = true;
|
|
|
|
keystroke.m_repeat = false;
|
|
|
|
keys.push_back(keystroke);
|
2002-05-05 19:38:09 +00:00
|
|
|
if (s_modifier[i].m_isToggle) {
|
2002-05-04 18:08:22 +00:00
|
|
|
keystroke.m_press = false;
|
|
|
|
keys.push_back(keystroke);
|
|
|
|
undo.push_back(keystroke);
|
|
|
|
keystroke.m_press = true;
|
|
|
|
undo.push_back(keystroke);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-05-04 18:08:22 +00:00
|
|
|
keystroke.m_press = false;
|
|
|
|
undo.push_back(keystroke);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
// modifier is active but should not be. if the
|
|
|
|
// modifier is a toggle then toggle it off with a
|
|
|
|
// press/release, otherwise deactivate it with a
|
|
|
|
// release. we must check each keycode for the
|
|
|
|
// modifier if not a toggle.
|
2002-05-05 19:38:09 +00:00
|
|
|
if (s_modifier[i].m_isToggle) {
|
|
|
|
keystroke.m_virtualKey = s_modifier[i].m_virtualKey;
|
2002-05-04 18:08:22 +00:00
|
|
|
keystroke.m_press = true;
|
|
|
|
keystroke.m_repeat = false;
|
|
|
|
keys.push_back(keystroke);
|
|
|
|
keystroke.m_press = false;
|
|
|
|
keys.push_back(keystroke);
|
|
|
|
undo.push_back(keystroke);
|
|
|
|
keystroke.m_press = true;
|
|
|
|
undo.push_back(keystroke);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-05-05 19:38:09 +00:00
|
|
|
UINT key = s_modifier[i].m_virtualKey;
|
2002-04-30 16:23:03 +00:00
|
|
|
if ((m_keys[key] & 0x80) != 0) {
|
2002-05-04 18:08:22 +00:00
|
|
|
keystroke.m_virtualKey = key;
|
|
|
|
keystroke.m_press = false;
|
|
|
|
keystroke.m_repeat = false;
|
|
|
|
keys.push_back(keystroke);
|
|
|
|
keystroke.m_press = true;
|
|
|
|
undo.push_back(keystroke);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
2002-05-05 19:38:09 +00:00
|
|
|
key = s_modifier[i].m_virtualKey2;
|
2002-05-04 18:08:22 +00:00
|
|
|
if (key != 0 && (m_keys[key] & 0x80) != 0) {
|
|
|
|
keystroke.m_virtualKey = key;
|
|
|
|
keystroke.m_press = false;
|
|
|
|
keystroke.m_repeat = false;
|
|
|
|
keys.push_back(keystroke);
|
|
|
|
keystroke.m_press = true;
|
|
|
|
undo.push_back(keystroke);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add the key event
|
2002-05-04 18:08:22 +00:00
|
|
|
switch (action) {
|
|
|
|
case kPress:
|
2002-05-05 19:38:09 +00:00
|
|
|
keystroke.m_virtualKey = virtualKey;
|
|
|
|
keystroke.m_press = true;
|
|
|
|
keystroke.m_repeat = false;
|
2002-05-04 18:08:22 +00:00
|
|
|
keys.push_back(keystroke);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kRelease:
|
2002-05-05 19:38:09 +00:00
|
|
|
keystroke.m_virtualKey = virtualKey;
|
|
|
|
keystroke.m_press = false;
|
|
|
|
keystroke.m_repeat = false;
|
2002-05-04 18:08:22 +00:00
|
|
|
keys.push_back(keystroke);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kRepeat:
|
2002-05-05 19:38:09 +00:00
|
|
|
keystroke.m_virtualKey = virtualKey;
|
|
|
|
keystroke.m_press = true;
|
|
|
|
keystroke.m_repeat = true;
|
2002-05-04 18:08:22 +00:00
|
|
|
keys.push_back(keystroke);
|
|
|
|
break;
|
|
|
|
}
|
2002-04-30 16:23:03 +00:00
|
|
|
|
|
|
|
// add key events to restore the modifier state. apply events in
|
|
|
|
// the reverse order that they're stored in undo.
|
|
|
|
while (!undo.empty()) {
|
|
|
|
keys.push_back(undo.back());
|
|
|
|
undo.pop_back();
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
// if the key is a modifier key then compute the modifier mask after
|
|
|
|
// this key is pressed.
|
|
|
|
mask = m_mask;
|
2002-05-04 18:08:22 +00:00
|
|
|
if (isModifier && action != kRepeat) {
|
|
|
|
// toggle keys modify the state on release. other keys set
|
|
|
|
// the bit on press and clear the bit on release.
|
2002-05-05 19:38:09 +00:00
|
|
|
const CModifierInfo& modifier = s_modifier[modifierIndex];
|
|
|
|
if (modifier.m_isToggle) {
|
2002-05-04 18:08:22 +00:00
|
|
|
if (action == kRelease) {
|
2002-05-05 19:38:09 +00:00
|
|
|
mask ^= modifier.m_mask;
|
2002-05-04 18:08:22 +00:00
|
|
|
}
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
2002-05-04 18:08:22 +00:00
|
|
|
else if (action == kPress) {
|
2002-05-05 19:38:09 +00:00
|
|
|
mask |= modifier.m_mask;
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// can't reset bit until all keys that set it are released.
|
|
|
|
// scan those keys to see if any are pressed.
|
|
|
|
bool down = false;
|
2002-05-05 19:38:09 +00:00
|
|
|
if (virtualKey != modifier.m_virtualKey &&
|
|
|
|
(m_keys[modifier.m_virtualKey] & 0x80) != 0) {
|
2002-04-30 16:23:03 +00:00
|
|
|
down = true;
|
|
|
|
}
|
2002-05-05 19:38:09 +00:00
|
|
|
if (modifier.m_virtualKey2 != 0 &&
|
|
|
|
virtualKey != modifier.m_virtualKey2 &&
|
|
|
|
(m_keys[modifier.m_virtualKey2] & 0x80) != 0) {
|
2002-04-30 16:23:03 +00:00
|
|
|
down = true;
|
|
|
|
}
|
|
|
|
if (!down)
|
2002-05-05 19:38:09 +00:00
|
|
|
mask &= ~modifier.m_mask;
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "previous modifiers 0x%04x, final modifiers 0x%04x", m_mask, mask));
|
2002-04-30 16:23:03 +00:00
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
2002-05-04 18:08:22 +00:00
|
|
|
void CMSWindowsSecondaryScreen::doKeystrokes(
|
|
|
|
const Keystrokes& keys, SInt32 count)
|
|
|
|
{
|
|
|
|
// do nothing if no keys or no repeats
|
|
|
|
if (count < 1 || keys.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// generate key events
|
|
|
|
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) {
|
|
|
|
if (k->m_repeat) {
|
|
|
|
// repeat from here up to but not including the next key
|
|
|
|
// with m_repeat == false count times.
|
|
|
|
Keystrokes::const_iterator start = k;
|
|
|
|
for (; count > 0; --count) {
|
|
|
|
// send repeating events
|
|
|
|
for (k = start; k != keys.end() && k->m_repeat; ++k) {
|
|
|
|
const UINT code = MapVirtualKey(k->m_virtualKey, 0);
|
|
|
|
keybd_event(k->m_virtualKey, code,
|
|
|
|
k->m_press ? 0 : KEYEVENTF_KEYUP, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// note -- k is now on the first non-repeat key after the
|
|
|
|
// repeat keys, exactly where we'd like to continue from.
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// send event
|
|
|
|
const UINT code = MapVirtualKey(k->m_virtualKey, 0);
|
|
|
|
keybd_event(k->m_virtualKey, code,
|
|
|
|
k->m_press ? 0 : KEYEVENTF_KEYUP, 0);
|
|
|
|
|
|
|
|
// next key
|
|
|
|
++k;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-30 16:23:03 +00:00
|
|
|
void CMSWindowsSecondaryScreen::updateKeys()
|
|
|
|
{
|
2002-05-04 18:08:22 +00:00
|
|
|
// GetKeyboardKeys() doesn't seem to do the expected thing
|
|
|
|
memset(m_keys, 0, sizeof(m_keys));
|
|
|
|
m_keys[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
|
|
|
|
m_keys[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
|
|
|
|
m_keys[VK_SHIFT] = GetKeyState(VK_SHIFT);
|
|
|
|
m_keys[VK_LCONTROL] = GetKeyState(VK_LCONTROL);
|
|
|
|
m_keys[VK_RCONTROL] = GetKeyState(VK_RCONTROL);
|
|
|
|
m_keys[VK_CONTROL] = GetKeyState(VK_CONTROL);
|
|
|
|
m_keys[VK_LMENU] = GetKeyState(VK_LMENU);
|
|
|
|
m_keys[VK_RMENU] = GetKeyState(VK_RMENU);
|
|
|
|
m_keys[VK_MENU] = GetKeyState(VK_MENU);
|
|
|
|
m_keys[VK_LWIN] = GetKeyState(VK_LWIN);
|
|
|
|
m_keys[VK_RWIN] = GetKeyState(VK_RWIN);
|
|
|
|
m_keys[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
|
|
|
|
m_keys[VK_NUMLOCK] = GetKeyState(VK_NUMLOCK);
|
|
|
|
m_keys[VK_SCROLL] = GetKeyState(VK_SCROLL);
|
2002-04-30 16:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::updateModifiers()
|
|
|
|
{
|
|
|
|
// update active modifier mask
|
|
|
|
m_mask = 0;
|
|
|
|
if ((m_keys[VK_LSHIFT] & 0x80) != 0 || (m_keys[VK_RSHIFT] & 0x80) != 0)
|
|
|
|
m_mask |= KeyModifierShift;
|
|
|
|
if ((m_keys[VK_LCONTROL] & 0x80) != 0 || (m_keys[VK_RCONTROL] & 0x80) != 0)
|
|
|
|
m_mask |= KeyModifierControl;
|
|
|
|
if ((m_keys[VK_LMENU] & 0x80) != 0 || (m_keys[VK_RMENU] & 0x80) != 0)
|
|
|
|
m_mask |= KeyModifierAlt;
|
|
|
|
if ((m_keys[VK_LWIN] & 0x80) != 0 || (m_keys[VK_RWIN] & 0x80) != 0)
|
|
|
|
m_mask |= KeyModifierMeta;
|
|
|
|
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
|
|
|
|
m_mask |= KeyModifierCapsLock;
|
|
|
|
if ((m_keys[VK_NUMLOCK] & 0x01) != 0)
|
|
|
|
m_mask |= KeyModifierNumLock;
|
|
|
|
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
|
|
|
m_mask |= KeyModifierScrollLock;
|
2002-05-04 18:08:22 +00:00
|
|
|
log((CLOG_DEBUG2 "modifiers on update: 0x%04x", m_mask));
|
2001-11-19 00:33:36 +00:00
|
|
|
}
|
2002-04-30 17:48:11 +00:00
|
|
|
|
|
|
|
void CMSWindowsSecondaryScreen::toggleKey(
|
|
|
|
UINT virtualKey, KeyModifierMask mask)
|
|
|
|
{
|
|
|
|
// send key events to simulate a press and release
|
|
|
|
const UINT code = MapVirtualKey(virtualKey, 0);
|
|
|
|
keybd_event(virtualKey, code, 0, 0);
|
|
|
|
keybd_event(virtualKey, code, KEYEVENTF_KEYUP, 0);
|
|
|
|
|
|
|
|
// toggle shadow state
|
|
|
|
m_mask ^= mask;
|
|
|
|
m_keys[virtualKey] ^= 0x01;
|
|
|
|
}
|