Changeset 2768 for trunk/synergy/lib/platform/CPMKeyState.cpp
- Timestamp:
- Aug 20, 2006, 8:11:44 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/synergy/lib/platform/CPMKeyState.cpp
r2765 r2768 28 28 29 29 // map virtual keys to synergy key enumeration 30 const KeyIDCPMKeyState::s_virtualKey[0x42] =31 { 32 /* 0x000 */ kKeyNone,// reserved33 /* 0x001 */ kKeyNone,// VK_BUTTON134 /* 0x002 */ kKeyNone,// VK_BUTTON235 /* 0x003 */ kKeyNone,// VK_BUTTON336 /* 0x004 */ kKeyBreak,// VK_BREAK37 /* 0x005 */ kKeyBackSpace,// VK_BACKSPACE38 /* 0x006 */ kKeyTab,// VK_TAB39 /* 0x007 */ kKeyLeftTab, // VK_BACKTAB -- ??? 40 /* 0x008 */ kKeyReturn,// VK_NEWLINE41 /* 0x009 */ kKeyShift_L,// VK_SHIFT42 /* 0x00a */ kKeyControl_L,// VK_CTRL43 /* 0x00b */ kKeyAlt_L,// VK_ALT44 /* 0x00c */ kKeyAltGr,// VK_ALTGRAF45 /* 0x00d */ kKeyPause,// VK_PAUSE46 /* 0x00e */ kKeyCapsLock,// VK_CAPSLOCK47 /* 0x00f */ kKeyEscape,// VK_ESC48 /* 0x010 */ kKeyNone,// VK_SPACE49 /* 0x011 */ kKeyPageUp,// VK_PAGEUP50 /* 0x012 */ kKeyPageDown,// VK_PAGEDOWN51 /* 0x013 */ kKeyEnd,// VK_END52 /* 0x014 */ kKeyHome,// VK_HOME53 /* 0x015 */ kKeyLeft,// VK_LEFT54 /* 0x016 */ kKeyUp,// VK_UP55 /* 0x017 */ kKeyRight,// VK_RIGHT56 /* 0x018 */ kKeyDown,// VK_DOWN57 /* 0x019 */ kKeyNone,// VK_PRINTSCRN58 /* 0x01a */ kKeyInsert,// VK_INSERT59 /* 0x01b */ kKeyDelete,// VK_DELETE60 /* 0x01c */ kKeyScrollLock,// VK_SCRLLOCK61 /* 0x01d */ kKeyNumLock,// VK_NUMLOCK62 /* 0x01e */ kKeyKP_Enter,// VK_ENTER63 /* 0x01f */ kKeySysReq,// VK_SYSRQ64 /* 0x020 */ kKeyF1,// VK_F165 /* 0x021 */ kKeyF2,// VK_F266 /* 0x022 */ kKeyF3,// VK_F367 /* 0x023 */ kKeyF4,// VK_F468 /* 0x024 */ kKeyF5,// VK_F569 /* 0x025 */ kKeyF6,// VK_F670 /* 0x026 */ kKeyF7,// VK_F771 /* 0x027 */ kKeyF8,// VK_F872 /* 0x028 */ kKeyF9,// VK_F973 /* 0x029 */ kKeyF10,// VK_F1074 /* 0x02a */ kKeyF11,// VK_F1175 /* 0x02b */ kKeyF12,// VK_F1276 /* 0x02c */ kKeyF13,// VK_F1377 /* 0x02d */ kKeyF14,// VK_F1478 /* 0x02e */ kKeyF15,// VK_F1579 /* 0x02f */ kKeyF16,// VK_F1680 /* 0x030 */ kKeyF17,// VK_F1781 /* 0x031 */ kKeyF18,// VK_F1882 /* 0x032 */ kKeyF19,// VK_F1983 /* 0x033 */ kKeyF20,// VK_F2084 /* 0x034 */ kKeyF21,// VK_F2185 /* 0x035 */ kKeyF22,// VK_F2286 /* 0x036 */ kKeyF23,// VK_F2387 /* 0x037 */ kKeyF24,// VK_F2488 /* 0x038 */ kKeyNone,// VK_ENDDRAG89 /* 0x039 */ kKeyClear,// VK_CLEAR90 /* 0x03a */ kKeyNone,// VK_EREOF91 /* 0x03b */ kKeyNone,// VK_PA192 /* 0x03c */ kKeyNone,// VK_ATTN93 /* 0x03d */ kKeyNone,// VK_CRSEL94 /* 0x03e */ kKeyNone,// VK_EXSEL95 /* 0x03f */ kKeyNone,// VK_COPY96 /* 0x040 */ kKeyNone,// VK_BLK197 /* 0x041 */ kKeyNone// VK_BLK230 const CPMKeyState::VirtualKey CPMKeyState::s_virtualKey[0x42] = 31 { 32 { /* 0x000 */ kKeyNone, 0, 0, 0 }, // reserved 33 { /* 0x001 */ kKeyNone, 0, 0, 0 }, // VK_BUTTON1 34 { /* 0x002 */ kKeyNone, 0, 0, 0 }, // VK_BUTTON2 35 { /* 0x003 */ kKeyNone, 0, 0, 0 }, // VK_BUTTON3 36 { /* 0x004 */ kKeyBreak, 0, 0, 0 }, // VK_BREAK 37 { /* 0x005 */ kKeyBackSpace, 8, 0, 0 }, // VK_BACKSPACE 38 { /* 0x006 */ kKeyTab, 9, 0, 0 }, // VK_TAB 39 { /* 0x007 */ kKeyLeftTab, 9, 0, 1 }, // VK_BACKTAB 40 { /* 0x008 */ kKeyReturn, 0x0d, 0, 0 }, // VK_NEWLINE 41 { /* 0x009 */ kKeyShift_L, 0, 0, 0 }, // VK_SHIFT 42 { /* 0x00a */ kKeyControl_L, 0, 0, 0 }, // VK_CTRL 43 { /* 0x00b */ kKeyAlt_L, 0, 0, 0 }, // VK_ALT 44 { /* 0x00c */ kKeyAltGr, 0, 0, 0 }, // VK_ALTGRAF 45 { /* 0x00d */ kKeyPause, 0, 0, 0 }, // VK_PAUSE 46 { /* 0x00e */ kKeyCapsLock, 0, 0, 0 }, // VK_CAPSLOCK 47 { /* 0x00f */ kKeyEscape, 0x1b, 0, 0 }, // VK_ESC 48 { /* 0x010 */ ' ', 0x20, 0, 0 }, // VK_SPACE 49 { /* 0x011 */ kKeyPageUp, 0xe0, 1, -1 }, // VK_PAGEUP 50 { /* 0x012 */ kKeyPageDown, 0xe0, 1, -1 }, // VK_PAGEDOWN 51 { /* 0x013 */ kKeyEnd, 0xe0, 1, -1 }, // VK_END 52 { /* 0x014 */ kKeyHome, 0xe0, 1, -1 }, // VK_HOME 53 { /* 0x015 */ kKeyLeft, 0xe0, 1, -1 }, // VK_LEFT 54 { /* 0x016 */ kKeyUp, 0xe0, 1, -1 }, // VK_UP 55 { /* 0x017 */ kKeyRight, 0xe0, 1, -1 }, // VK_RIGHT 56 { /* 0x018 */ kKeyDown, 0xe0, 1, -1 }, // VK_DOWN 57 { /* 0x019 */ kKeyNone, 0xe0, 0, 0 }, // VK_PRINTSCRN 58 { /* 0x01a */ kKeyInsert, 0xe0, 1, 1 }, // VK_INSERT 59 { /* 0x01b */ kKeyDelete, 0xe0, 1, 1 }, // VK_DELETE 60 { /* 0x01c */ kKeyScrollLock, 0, 0, 0 }, // VK_SCRLLOCK 61 { /* 0x01d */ kKeyNumLock, 0, 0, 0 }, // VK_NUMLOCK 62 { /* 0x01e */ kKeyKP_Enter, 0x0d, 1, 1 }, // VK_ENTER 63 { /* 0x01f */ kKeySysReq, 0, 0, 0 }, // VK_SYSRQ 64 { /* 0x020 */ kKeyF1, 0, 0, 1 }, // VK_F1 65 { /* 0x021 */ kKeyF2, 0, 0, 1 }, // VK_F2 66 { /* 0x022 */ kKeyF3, 0, 0, 1 }, // VK_F3 67 { /* 0x023 */ kKeyF4, 0, 0, 1 }, // VK_F4 68 { /* 0x024 */ kKeyF5, 0, 0, 1 }, // VK_F5 69 { /* 0x025 */ kKeyF6, 0, 0, 1 }, // VK_F6 70 { /* 0x026 */ kKeyF7, 0, 0, 1 }, // VK_F7 71 { /* 0x027 */ kKeyF8, 0, 0, 1 }, // VK_F8 72 { /* 0x028 */ kKeyF9, 0, 0, 1 }, // VK_F9 73 { /* 0x029 */ kKeyF10, 0, 0, 1 }, // VK_F10 74 { /* 0x02a */ kKeyF11, 0, 0, 1 }, // VK_F11 75 { /* 0x02b */ kKeyF12, 0, 0, 1 }, // VK_F12 76 { /* 0x02c */ kKeyF13, 0, 0, 1 }, // VK_F13 77 { /* 0x02d */ kKeyF14, 0, 0, 1 }, // VK_F14 78 { /* 0x02e */ kKeyF15, 0, 0, 1 }, // VK_F15 79 { /* 0x02f */ kKeyF16, 0, 0, 1 }, // VK_F16 80 { /* 0x030 */ kKeyF17, 0, 0, 1 }, // VK_F17 81 { /* 0x031 */ kKeyF18, 0, 0, 1 }, // VK_F18 82 { /* 0x032 */ kKeyF19, 0, 0, 1 }, // VK_F19 83 { /* 0x033 */ kKeyF20, 0, 0, 1 }, // VK_F20 84 { /* 0x034 */ kKeyF21, 0, 0, 1 }, // VK_F21 85 { /* 0x035 */ kKeyF22, 0, 0, 1 }, // VK_F22 86 { /* 0x036 */ kKeyF23, 0, 0, 1 }, // VK_F23 87 { /* 0x037 */ kKeyF24, 0, 0, 1 }, // VK_F24 88 { /* 0x038 */ kKeyNone, 0, 0, 0 }, // VK_ENDDRAG 89 { /* 0x039 */ kKeyNone, 0, 0, 0 }, // VK_CLEAR 90 { /* 0x03a */ kKeyNone, 0, 0, 0 }, // VK_EREOF 91 { /* 0x03b */ kKeyNone, 0, 0, 0 }, // VK_PA1 92 { /* 0x03c */ kKeyNone, 0, 0, 0 }, // VK_ATTN 93 { /* 0x03d */ kKeyNone, 0, 0, 0 }, // VK_CRSEL 94 { /* 0x03e */ kKeyNone, 0, 0, 0 }, // VK_EXSEL 95 { /* 0x03f */ kKeyNone, 0, 0, 0 }, // VK_COPY 96 { /* 0x040 */ kKeyNone, 0, 0, 0 }, // VK_BLK1 97 { /* 0x041 */ kKeyNone, 0, 0, 0 }, // VK_BLK2 98 98 }; 99 99 … … 354 354 } 355 355 356 static USHORT 357 convertKeyModiferMaskToTCF(const KeyModifierMask mask) 358 { 359 USHORT fShiftState = 0; 360 if (mask & KeyModifierShift) fShiftState |= TCF_SHIFT; 361 if (mask & KeyModifierControl) fShiftState |= TCF_CONTROL; 362 if (mask & KeyModifierAlt) fShiftState |= TCF_ALT; 363 if (mask & KeyModifierAltGr) fShiftState |= TCF_ALTGR; 364 if (mask & KeyModifierCapsLock) fShiftState |= TCF_CAPSLOCK; 365 if (mask & KeyModifierNumLock) fShiftState |= TCF_NUMLOCK; 366 return fShiftState; 367 } 368 369 static KeyModifierMask 370 convertTCFToKeyModiferMask(const USHORT fShiftState) 371 { 372 KeyModifierMask mask = 0; 373 if (fShiftState & TCF_SHIFT) mask |= KeyModifierShift; 374 if (fShiftState & TCF_CONTROL) mask |= KeyModifierControl; 375 if (fShiftState & TCF_ALT) mask |= KeyModifierAlt; 376 if (fShiftState & TCF_ALTGR) mask |= KeyModifierAltGr; 377 if (fShiftState & TCF_CAPSLOCK) mask |= KeyModifierCapsLock; 378 if (fShiftState & TCF_NUMLOCK) mask |= KeyModifierNumLock; 379 return mask; 380 } 381 382 static bool 383 isASCIIControlChar(const USHORT usChar) 384 { 385 switch (usChar) { 386 /* Skip the ones with virtual keys. */ 387 case 0x08 + 0x40: case 0x08 + 0x60: // backspace 388 case 0x09 + 0x40: case 0x09 + 0x60: // horizontal tab 389 case 0x1b + 0x40: case 0x1b + 0x60: // escape 390 case 0x0d + 0x40: case 0x0d + 0x60: // return 391 return false; 392 default: 393 return (usChar >= 'A' && usChar <= '_') 394 || (usChar >= 'a' && usChar <= 'z'); 395 } 396 } 397 398 void 399 CPMKeyState::convertScancodes(ClientData *pData) 400 { 401 /* 402 * This is a bit tricky / hackish, but what we have to do here is to 403 * deal with extended keys and the keypad stuff. The scancode 404 * translation tables doesn't seem to be 100% correct for these 405 * keys, and these keys are the ones we need them the most. sigh. 406 */ 407 408 // 409 // navigation and insert/delete buttons left of the numpad: 410 // home, up, pgup, left, right, end, down, pgdn, insert, delete 411 // 412 // The pm and translated scancodes are mixed up in these cases. 413 // The keys are all extended and secondary. 414 // 415 if ( pData->s.xlatScan >= 0x60 /* VK_HOME */ 416 && pData->s.xlatScan <= 0x69 /* VK_DELETE */ 417 && pData->s.virtualKey != 0) { 418 pData->s.scan = pData->s.xlatScan; 419 pData->s.xlatScan = m_pmScanToOemScanExt[pData->s.xlatScan]; 420 pData->s.fExtendedKey = true; 421 pData->s.fNeedNumUnlockKey = true; 422 pData->s.fSecondary = true; 423 return; 424 } 425 426 // 427 // There are some virtual keys we know are extended, mark them so (like the Fxx keys). 428 // 429 if ( pData->s.virtualKey < sizeof(s_virtualKey) / sizeof(s_virtualKey[0]) 430 && !pData->s.fExtendedKey) { 431 if ( s_virtualKey[pData->s.virtualKey].extended == 1 432 || ( s_virtualKey[pData->s.virtualKey].extended == -1 433 && ( pData->s.xlatChar == 0 434 || pData->s.xlatChar == s_virtualKey[pData->s.virtualKey].ch))) { 435 pData->s.fExtendedKey = true; 436 } 437 } 438 439 // 440 // Do the translating. 441 // 442 if (pData->s.xlatScan == pData->s.scan) { 443 pData->s.scan = m_pmScanToOemScan[pData->s.xlatScan]; 444 //if (pData->s.fExtendedKey) { 445 // pData->s.scan = m_pmScanToOemScanExt[pData->s.xlatScan]; 446 //} else { 447 // pData->s.scan = m_pmScanToOemScan[pData->s.xlatScan]; 448 //} 449 } 450 } 451 452 356 453 void 357 454 CPMKeyState::getKeyMap(CKeyMap& keyMap) … … 375 472 376 473 CKeyMap::KeyItem item; 377 // SInt32 numGroups = (SInt32)m_groups.size();378 // for (SInt32 g = 0; g < numGroups; ++g) {379 474 for (SInt32 g = 0; g < 1; ++g) { 380 475 item.m_group = g; 381 // ActivateKeyboardLayout(m_groups[g], 0); 382 383 // clear tables 476 477 // 478 // Fill the scan code conversion tables. 479 // 480 for (unsigned i = 0; i < sizeof(m_pmScanToOemScan) / sizeof(m_pmScanToOemScan[0]); i++) { 481 USHORT us = i; 482 USHORT fShiftState = 0; 483 WinTranslateChar2(0, &us, NULL, TC_SCANTOOEMSCAN, &fShiftState); 484 m_pmScanToOemScan[i] = us; 485 } 486 for (unsigned i = 0; i < sizeof(m_pmScanToOemScanExt) / sizeof(m_pmScanToOemScanExt[0]); i++) { 487 USHORT us = i; 488 USHORT fShiftState = TCF_EXTENDEDKEY; 489 WinTranslateChar2(0, &us, NULL, TC_SCANTOOEMSCAN, &fShiftState); 490 m_pmScanToOemScanExt[i] = us; 491 } 492 for (unsigned i = 0; i < sizeof(m_oemScanToPmScan) / sizeof(m_oemScanToPmScan[0]); i++) { 493 USHORT us = i; 494 USHORT fShiftState = 0; 495 WinTranslateChar2(0, &us, NULL, TC_OEMSCANTOSCAN, &fShiftState); 496 m_oemScanToPmScan[i] = us; 497 } 498 for (unsigned i = 0; i < sizeof(m_oemScanToPmScanExt) / sizeof(m_oemScanToPmScanExt[0]); i++) { 499 USHORT us = i; 500 USHORT fShiftState = TCF_EXTENDEDKEY; 501 WinTranslateChar2(0, &us, NULL, TC_OEMSCANTOSCAN, &fShiftState); 502 m_oemScanToPmScanExt[i] = us; 503 } 504 505 506 // 507 // map buttons (scancodes) to virtual keys 508 // 384 509 memset(m_buttonToVK, 0, sizeof(m_buttonToVK)); 385 386 // map buttons (scancodes) to virtual keys387 510 for (KeyButton i = 1; i < 256; ++i) { 388 511 USHORT usVirtualKey = i; … … 394 517 } 395 518 } 519 520 /// @todo the stuff down to the button loop isn't really done yet. 396 521 397 522 // now map virtual keys to buttons. multiple virtual keys may map … … 406 531 case VK_BUTTON2: 407 532 case VK_BUTTON3: 408 case VK_SHIFT:409 case VK_CTRL:410 533 case VK_MENU: 411 534 continue; … … 423 546 } 424 547 } 425 426 /// @todo?427 // // add alt+printscreen428 // if (m_buttonToVK[0x54u] == 0) {429 // m_buttonToVK[0x54u] = VK_SNAPSHOT;430 // }431 548 432 549 // set virtual key to button table … … 441 558 // } 442 559 443 // add the keys to the map. 444 BYTE keys[256]; 445 memset(keys, 0, sizeof(keys)); 446 for (KeyButton i = 0; i < 512; ++i) { 560 // 561 // Add the keys to the map. 562 // 563 //for (KeyButton i = 0; i < 256; ++i) { 564 for (KeyButton i = 0; i < 256; ++i) { 565 // 566 // Does this translate to a virtual key or character? 567 // 447 568 USHORT usChar = i; 448 USHORT fCharShiftState = 0; 449 USHORT fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOVIRTUALKEY, &fCharShiftState); 569 USHORT fShiftState = 0; 570 USHORT fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOCHAR, &fShiftState); 571 USHORT usVirtualKey = i; 572 USHORT fVirtualKeyKCFlags = WinTranslateChar2(0, &usVirtualKey, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 573 if (!usChar && !usVirtualKey) { 574 // try with control down. 575 usChar = i; 576 fShiftState = TCF_CONTROL; 577 fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOCHAR, &fShiftState); 578 usVirtualKey = i; 579 fShiftState = TCF_CONTROL; 580 fVirtualKeyKCFlags = WinTranslateChar2(0, &usVirtualKey, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 581 } 582 if (!usChar && !usVirtualKey) { 583 // try with altgr down. 584 usChar = i; 585 fShiftState = TCF_ALTGR; 586 fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOCHAR, &fShiftState); 587 usVirtualKey = i; 588 fShiftState = TCF_ALTGR; 589 fVirtualKeyKCFlags = WinTranslateChar2(0, &usVirtualKey, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 590 } 591 if (!usChar && !usVirtualKey) { 592 // try with numlock toggled. 593 usChar = i; 594 fShiftState = TCF_NUMLOCK; 595 fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOCHAR, &fShiftState); 596 usVirtualKey = i; 597 fShiftState = TCF_NUMLOCK; 598 fVirtualKeyKCFlags = WinTranslateChar2(0, &usVirtualKey, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 599 } 450 600 if ( usChar 451 || m_buttonToVK[i]) {452 // initialize item453 item.m_id = getKeyID(m_buttonToVK[i], i );601 || usVirtualKey) { 602 // initialize the item 603 item.m_id = getKeyID(m_buttonToVK[i], i, false, usChar); 454 604 item.m_button = i; 455 605 item.m_required = 0; 456 606 item.m_sensitive = 0; 457 item.m_client = (m_buttonToVK[i] & 0xff) // 0-7 : virtual key. 458 | (i << 8) // 8-15: scancode 459 | (usChar & 0x3fff) // 16-29: PM char 460 | (0 << 30) // 30: KC_DEADKEY ?? 461 | (0 << 31); // 31: KC_COMPOSITE ?? 607 item.m_dead = false; 608 item.m_lock = false; 462 609 463 610 // get flags for modifier keys 464 611 CKeyMap::initModifierKey(item); 465 466 if (item.m_id == 0) { 467 #if 0 468 // translate virtual key to a character with and without 469 // shift, caps lock, and AltGr. 470 struct Modifier { 471 ULONG m_vk1; 472 ULONG m_vk2; 473 BYTE m_state; 474 KeyModifierMask m_mask; 475 }; 476 static const Modifier modifiers[] = { 477 { VK_SHIFT, VK_SHIFT, 0x80u, KeyModifierShift }, 478 { VK_CAPITAL, VK_CAPITAL, 0x01u, KeyModifierCapsLock }, 479 { VK_CONTROL, VK_MENU, 0x80u, KeyModifierControl | KeyModifierAlt } 480 }; 481 static const size_t s_numModifiers = sizeof(modifiers) / sizeof(modifiers[0]); 482 static const size_t s_numCombinations = 1 << s_numModifiers; 483 KeyID id[s_numCombinations]; 484 485 bool anyFound = false; 486 KeyButton button = static_cast<KeyButton>(i & 0xffu); 487 for (size_t j = 0; j < s_numCombinations; ++j) { 488 for (size_t k = 0; k < s_numModifiers; ++k) { 489 if ((j & (1 << k)) != 0) { 490 keys[modifiers[k].m_vk1] = modifiers[k].m_state; 491 keys[modifiers[k].m_vk2] = modifiers[k].m_state; 492 } 493 else { 494 keys[modifiers[k].m_vk1] = 0; 495 keys[modifiers[k].m_vk2] = 0; 496 } 497 } 498 id[j] = getIDForKey(item, button, m_buttonToVK[i], keys, m_groups[g]); 499 if (id[j] != 0) { 500 anyFound = true; 501 } 502 } 503 504 if (anyFound) { 505 // determine what modifiers we're sensitive to. 506 // we're sensitive if the KeyID changes when the 507 // modifier does. 508 item.m_sensitive = 0; 509 for (size_t k = 0; k < s_numModifiers; ++k) { 510 for (size_t j = 0; j < s_numCombinations; ++j) { 511 if (id[j] != id[j ^ (1u << k)]) { 512 item.m_sensitive |= modifiers[k].m_mask; 513 break; 514 } 515 } 516 } 517 518 // save each key. the map will automatically discard 519 // duplicates, like an unshift and shifted version of 520 // a key that's insensitive to shift. 521 for (size_t j = 0; j < s_numCombinations; ++j) { 522 item.m_id = id[j]; 523 item.m_required = 0; 524 for (size_t k = 0; k < s_numModifiers; ++k) { 525 if ((j & (1 << k)) != 0) { 526 item.m_required |= modifiers[k].m_mask; 527 } 528 } 529 addKeyEntry(keyMap, item); 530 } 531 } 532 #endif 533 } else { 534 // found in table - adjust modifiers and add it. 535 switch (m_buttonToVK[i]) { 536 case VK_BACKTAB: 537 item.m_required |= KeyModifierShift; 538 item.m_sensitive |= KeyModifierShift; 539 break; 540 } 541 addKeyEntry(keyMap, item); 542 } 543 } 544 } // for buttons 0 thru 511 612 if (item.m_generates != 0) { 613 // it's a modifier key. 614 item.m_lock = usVirtualKey == VK_NUMLOCK 615 || usVirtualKey == VK_SCRLLOCK 616 || usVirtualKey == VK_CAPSLOCK; 617 ClientData data; 618 data.u = 0; 619 data.s.scan = i; 620 data.s.xlatScan = i; 621 data.s.fShiftKey = true; 622 data.s.xlatChar = usChar; 623 data.s.virtualKey = usVirtualKey; 624 convertScancodes(&data); 625 item.m_client = data.u; 626 addKeyEntry(keyMap, item); 627 } else { 628 // 629 // Check which keys it might be sensitive to. 630 // We assume (possibly incorrectly) that combinations doesn't matter... :) 631 // 632 static const struct { 633 KeyModifierMask mask; 634 unsigned fShiftState; 635 } modifiers[] = { 636 { KeyModifierShift, TCF_SHIFT}, 637 { KeyModifierControl, TCF_CONTROL }, 638 { KeyModifierAlt, TCF_ALT }, 639 { KeyModifierAltGr, TCF_ALTGR }, 640 { KeyModifierCapsLock, TCF_CAPSLOCK }, 641 { KeyModifierNumLock, TCF_NUMLOCK } 642 }; 643 usChar = i; 644 fShiftState = 0; 645 fCharKCFlags = WinTranslateChar2(0, &usChar, NULL, TC_SCANCODETOCHAR, &fShiftState); 646 usVirtualKey = i; 647 fShiftState = 0; 648 fVirtualKeyKCFlags = WinTranslateChar2(0, &usVirtualKey, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 649 for (unsigned j = 0; j < sizeof(modifiers) / sizeof(modifiers[0]); j++) { 650 USHORT usCh = i; 651 fShiftState = modifiers[j].fShiftState; 652 if ( WinTranslateChar2(0, &usCh, NULL, TC_SCANCODETOCHAR, &fShiftState) != 0 653 && usCh != 0 654 && usCh != usChar) { 655 item.m_sensitive |= modifiers[j].mask; 656 continue; 657 } 658 usCh = i; 659 fShiftState = modifiers[j].fShiftState; 660 WinTranslateChar2(0, &usCh, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 661 if ( usCh != 0 662 && usCh != usVirtualKey) { 663 item.m_sensitive |= modifiers[j].mask; 664 continue; 665 } 666 } 667 if (isASCIIControlChar(usChar)) { 668 item.m_sensitive |= KeyModifierControl; 669 } 670 671 // 672 // Check for numpad keys. We need to adjust stuff then. 673 // It think this test should be sufficient. 674 // 675 bool numpad = (item.m_sensitive & KeyModifierNumLock) != 0; 676 677 // 678 // Unoptimized brute force algorithm for determining the 679 // possible combinations and adding them to the key map. 680 // 681 struct 682 { 683 UCHAR uchChar; 684 UCHAR uchVirtualKey; 685 } combinations[1 << TCF_MAX_BITS]; 686 687 for (unsigned j = 0; j < sizeof(combinations) / sizeof(combinations[0]); j++) { 688 const KeyModifierMask mask = convertTCFToKeyModiferMask(j); 689 if ((mask & item.m_sensitive) != mask /*|| j>3*/) { 690 combinations[j].uchChar = combinations[j].uchVirtualKey = 0; 691 continue; 692 } 693 // get any character value 694 USHORT us = i; 695 fShiftState = j; 696 if (WinTranslateChar2(0, &us, NULL, TC_SCANCODETOCHAR, &fShiftState) == 0) { 697 us = 0; 698 } 699 combinations[j].uchChar = us; 700 701 // get any virtual key value 702 us = i; 703 fShiftState = j; 704 WinTranslateChar2(0, &us, NULL, TC_SCANCODETOVIRTUALKEY, &fShiftState); 705 combinations[j].uchVirtualKey = us; 706 707 // deal with missing character translations 708 if ( combinations[j].uchChar == 0 709 && us != 0 710 && us < sizeof(s_virtualKey) / sizeof(s_virtualKey[0])) { 711 combinations[j].uchChar = s_virtualKey[us].ch; 712 } 713 } 714 715 // 2. Eliminate duplicates. 716 for (unsigned j = 0; j < sizeof(combinations) / sizeof(combinations[0]); j++) { 717 unsigned best = j; 718 KeyModifierMask bestMask = convertTCFToKeyModiferMask(j); 719 for (unsigned k = j + 1; k < sizeof(combinations) / sizeof(combinations[0]); k++) { 720 if ( combinations[best].uchChar == combinations[k].uchChar 721 && combinations[best].uchVirtualKey == combinations[k].uchVirtualKey) { 722 const KeyModifierMask mask = convertTCFToKeyModiferMask(k); 723 // drop L/R mixes. 724 if (mask == bestMask) { 725 combinations[k].uchChar = combinations[k].uchVirtualKey = 0; 726 } 727 } 728 } 729 } 730 731 // 3. Add the remainders. 732 for (unsigned j = 0; j < sizeof(combinations) / sizeof(combinations[0]); j++) { 733 if (combinations[j].uchChar || combinations[j].uchVirtualKey) { 734 USHORT usChar = combinations[j].uchChar; 735 USHORT usVirtualKey = combinations[j].uchVirtualKey; 736 737 // update the changing item members 738 item.m_required = convertTCFToKeyModiferMask(j); 739 if (usVirtualKey) { 740 switch (usVirtualKey) { 741 case VK_BACKTAB: 742 item.m_required |= KeyModifierShift; 743 item.m_sensitive |= KeyModifierShift; 744 usChar = 0; // this one is translated incorrectly 745 break; 746 } 747 item.m_id = getKeyID(usVirtualKey, i, numpad, usChar); 748 } else { 749 item.m_id = usChar; /// @todo translate to unicode! 750 } 751 ClientData data; 752 data.u = 0; 753 data.s.scan = i; 754 data.s.xlatScan = i; 755 data.s.xlatChar = usChar; 756 data.s.virtualKey = usVirtualKey; 757 convertScancodes(&data); 758 item.m_client = data.u; 759 addKeyEntry(keyMap, item); 760 } 761 } 762 763 // 4. ASCII Control Character variants. (ARG! this doesn't work, fakeMsg hacks it.) 764 if (isASCIIControlChar(usChar)) { 765 /* add key */ 766 item.m_id = usChar - (usChar >= 'a' ? 0x60 : 0x40); 767 item.m_required = KeyModifierControl; 768 ClientData data; 769 data.u = 0; 770 data.s.scan = i; 771 data.s.xlatScan = i; 772 data.s.xlatChar = item.m_id; 773 convertScancodes(&data); 774 item.m_client = data.u; 775 addKeyEntry(keyMap, item); 776 item.m_id = usChar; 777 addKeyEntry(keyMap, item); 778 } 779 } 780 } 781 } // for buttons 0 thru 254 782 783 // 784 // Various other keys for which we don't expect the above loops to catch. 785 // 786 item.m_id = kKeyMenu; 787 item.m_button = 0xee; 788 item.m_required = 0; 789 item.m_sensitive = 0; 790 item.m_dead = false; 791 item.m_lock = false; 792 ClientData data; 793 data.u = 0; 794 data.s.scan = 0x7c; 795 data.s.xlatScan = 0xee; 796 data.s.fSecondary = true; 797 data.s.fExtendedKey = true; 798 data.s.fNeedNumUnlockKey = true; 799 item.m_client = data.u; 800 CKeyMap::initModifierKey(item); 801 addKeyEntry(keyMap, item); 802 803 item.m_id = kKeySuper_L; 804 item.m_button = 0xec; 805 data.s.xlatScan = 0xec; 806 data.s.scan = 0x7e; 807 item.m_client = data.u; 808 CKeyMap::initModifierKey(item); 809 addKeyEntry(keyMap, item); 810 811 item.m_id = kKeySuper_R; 812 item.m_button = 0xed; 813 data.s.xlatScan = 0xed; 814 data.s.scan = 0x7f; 815 item.m_client = data.u; 816 CKeyMap::initModifierKey(item); 817 addKeyEntry(keyMap, item); 818 545 819 } 546 820 … … 557 831 switch (keystroke.m_type) { 558 832 case Keystroke::kButton: { 559 LOG((CLOG_DEBUG1 " %03x (%08 x) %s%s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client,833 LOG((CLOG_DEBUG1 " %03x (%08llx) %s%s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, 560 834 keystroke.m_data.m_button.m_press ? "down" : "up", keystroke.m_data.m_button.m_repeat ? " repeate" : "")); 561 835 KeyButton button = keystroke.m_data.m_button.m_button; … … 569 843 570 844 // unpack the m_client packet. 571 USHORT virtualKey = 0;//keystroke.m_data.m_button.m_client & 0xff; 572 UCHAR scanCode = (keystroke.m_data.m_button.m_client >> 8) & 0xff; 573 USHORT pmChar = 0;//(keystroke.m_data.m_button.m_client >> 16) & 0xff; 574 bool fKC_DEADKEY = (keystroke.m_data.m_button.m_client >> 30) & 1; 575 bool fKC_COMPOSITE = (keystroke.m_data.m_button.m_client >> 31) & 1; 576 845 ClientData data; 846 data.u = keystroke.m_data.m_button.m_client; 847 848 // 577 849 // synthesize message 850 // There are two options at this point, WM_CHAR or WM_VIOCHAR. It seems 851 // like WM_VIOCHAR is the better choice since that's the form in which 852 // keyboard events normally arrive in the system queue. 853 // 854 // WM_VIOCHAR: 855 // mp1.s1: KC_ flags. 856 // mp1.c3: repeat 857 // mp1.c4: scancode 858 // mp2.c1: translated char 859 // mp2.c2: translated scancode 860 // mp2.s2: KDD_ flags. 861 // 862 863 // the standard bits. 578 864 HAB hab = CPMUtil::getHAB();/// @todo fix this 579 865 QMSG qmsg; 580 866 qmsg.hwnd = NULLHANDLE; 581 qmsg.msg = WM_ CHAR;867 qmsg.msg = WM_VIOCHAR; 582 868 qmsg.ptl.x = 0; 583 869 qmsg.ptl.y = 0; … … 585 871 qmsg.reserved = 0; 586 872 587 // mp2 588 if (!keystroke.m_data.m_button.m_press) { 589 pmChar |= 0x0e00; /// @todo figure out what's going on here... 873 // 874 // calc the key code flags. 875 // PM deals with: KC_TOGGLE, KC_VIRTUALKEY, KC_CHAR, (WM_CHAR: also KC_CTRL, KC_ALT, KC_SHIFT). 876 // 877 USHORT fKC = 0; 878 if (data.s.scan) 879 fKC |= KC_SCANCODE; 880 if (!keystroke.m_data.m_button.m_press) 881 fKC |= KC_KEYUP; 882 /// @todo check that PM does KC_INVALIDCOMP 883 if (data.s.fDeadKey) 884 fKC |= KC_DEADKEY; 885 if (data.s.fComposite) 886 fKC |= KC_COMPOSITE; 887 if (!keystroke.m_data.m_button.m_press && m_lastButton == data.s.scan) 888 fKC |= KC_LONEKEY; 889 890 // we need these for calcing fKDD, so just put them in even if PM can do it for us. 891 KeyModifierMask modifierMask = this->getActiveModifiers(); 892 if (modifierMask & KeyModifierShift) 893 fKC |= KC_SHIFT; 894 if (modifierMask & KeyModifierControl) 895 fKC |= KC_CTRL; 896 if (modifierMask & KeyModifierAlt) 897 fKC |= KC_ALT; 898 899 // 900 // Calc the keyboard device driver flags. 901 // 902 USHORT fKDD; 903 // the action 904 if (data.s.fShiftKey) 905 fKDD = KDD_SHIFTKEY; 906 /** @todo Determin the KDD_ACTIONMASK value. 907 KDD_PREFIXKEY 908 KDD_PAUSEKEY 909 KDD_PSEUDOPAUSE 910 KDD_WAKEUPKEY 911 KDD_BREAKKEY 912 KDD_PSEUDOBREAK 913 KDD_PRTECHOKEY 914 KDD_PSEUDOPRECH */ 915 else 916 fKDD = KDD_PUTINKIB; 917 #if 0 918 if (fKC & KC_LONEKEY) fKDD |= KDD_KC_LONEKEY; 919 if (fKC & KC_PREVDOWN) fKDD |= KDD_KC_PREVDOWN; 920 if (fKC & KC_KEYUP) fKDD |= KDD_KC_KEYUP | KDD_BREAK; 921 if (fKC & KC_ALT) fKDD |= KDD_KC_ALT; 922 if (fKC & KC_CTRL) fKDD |= KDD_KC_CTRL; 923 if (fKC & KC_SHIFT) fKDD |= KDD_KC_SHIFT; 924 #else 925 if (fKC & KC_KEYUP) fKDD |= KDD_BREAK; 926 #endif 927 if (data.s.fSecondary) fKDD |= KDD_SECONDARY; 928 if (data.s.fExtendedKey) fKDD |= KDD_EXTENDEDKEY; 929 930 // 931 // Adjust char for ASCII control keys. (Ctrl+C and stuff) 932 // 933 if ( (fKC & KC_CTRL) 934 && isASCIIControlChar(data.s.xlatChar)) { 935 data.s.xlatChar -= (data.s.xlatChar >= 'a' ? 0x60 : 0x40); 590 936 } 591 qmsg.mp2 = MPFROM2SHORT(pmChar, virtualKey); 592 593 // mp1 594 USHORT fFlags = 0; 595 if (!keystroke.m_data.m_button.m_press) { 596 fFlags |= KC_KEYUP; 597 /// @todo KC_LONEKEY and KC_TOGGLE, or will PM take care of that? 937 938 // 939 // For some keys (navigation and edit keys left to the numpad), 940 // any numlock or shift needs to be 'canceled'. 941 // (At least this happens with my logitech diNovo keyboards.) 942 // 943 if ( data.s.fNeedNumUnlockKey 944 && ( (modifierMask & (KeyModifierShift | KeyModifierNumLock)) == KeyModifierNumLock 945 || (modifierMask & (KeyModifierShift | KeyModifierNumLock)) == KeyModifierShift)) { 946 // need to insert a key nullifying the numlock/shift. 947 QMSG qmsg0 = qmsg; 948 qmsg0.mp1 = MPFROMSH2CH(fKC & KC_KEYUP, 1, 0); 949 qmsg0.mp2 = MPFROM2SHORT(MAKESHORT(0, 0x2a), (fKDD & KDD_BREAK) | KDD_UNDEFINED | KDD_SECONDARY | KDD_EXTENDEDKEY); 950 951 // this message comes first on keydown and last on keyup. 952 if (fKC & KC_KEYUP) { 953 QMSG tmp = qmsg; 954 qmsg = qmsg0; 955 qmsg0 = tmp; 956 } 957 958 LOG((CLOG_INFO "WM_VIOCHAR: fKC=%04x rep=%02x scan=%02x xlch=%02x(%c) xlscan=%02x fKDD=%04x ", 959 SHORT1FROMMP(qmsg0.mp1), CHAR3FROMMP(qmsg0.mp1), CHAR4FROMMP(qmsg0.mp1), CHAR1FROMMP(qmsg0.mp2), 960 isprint(CHAR1FROMMP(qmsg0.mp2)) ? CHAR1FROMMP(qmsg0.mp2) : '.', CHAR2FROMMP(qmsg0.mp2), SHORT2FROMMP(qmsg0.mp2))); 961 const char *pszError = m_fakeMsg(hab, &qmsg0); 962 if (pszError) { 963 LOG((CLOG_ERR " fakeMsg failed to inject msg=%#lx mp1=%#lx mp2=%#lx: %s", qmsg0.msg, qmsg0.mp1, qmsg0.mp2, pszError)); 964 } 598 965 } 599 /// @todo check that PM does KC_CTRL, KC_ALT and KC_SHIFT. 600 /// @todo check that PM does KC_INVALIDCOMP 601 if (fKC_DEADKEY) fFlags |= KC_DEADKEY; 602 if (fKC_COMPOSITE) fFlags |= KC_COMPOSITE; 603 // if (virtualKey) fFlags |= KC_VIRTUALKEY; 604 // if (keystroke.m_data.m_button.m_press && pmChar) 605 // fFlags |= KC_CHAR; 606 if (scanCode) fFlags |= KC_SCANCODE; 607 if (!keystroke.m_data.m_button.m_press && m_lastButton == scanCode) 608 fFlags |= KC_LONEKEY; 609 // PM does: KC_TOGGLE, KC_CTRL, KC_ALT, KC_SHIFT. more? 610 qmsg.mp1 = MPFROMSH2CH(fFlags, 1, scanCode); /** @todo translate the scan code back to its untranslated form. */ 611 612 // finaly inject it. 966 967 // 968 // Inject the (last) message. 969 // 970 qmsg.mp1 = MPFROMSH2CH(fKC, 1, data.s.scan); 971 qmsg.mp2 = MPFROM2SHORT(MAKESHORT(data.s.xlatChar, data.s.xlatScan), fKDD); 972 LOG((CLOG_INFO "WM_VIOCHAR: fKC=%04x rep=%02x scan=%02x xlch=%02x(%c) xlscan=%02x fKDD=%04x ", 973 SHORT1FROMMP(qmsg.mp1), CHAR3FROMMP(qmsg.mp1), CHAR4FROMMP(qmsg.mp1), CHAR1FROMMP(qmsg.mp2), 974 isprint(CHAR1FROMMP(qmsg.mp2)) ? CHAR1FROMMP(qmsg.mp2) : '.', CHAR2FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2))); 613 975 const char *pszError = m_fakeMsg(hab, &qmsg); 614 976 if (pszError) { … … 618 980 // remember the previous key for KC_LONEKEY. 619 981 if (keystroke.m_data.m_button.m_press && !keystroke.m_data.m_button.m_repeat) 620 m_lastButton = scanCode;982 m_lastButton = data.s.scan; 621 983 break; 622 984 } … … 654 1016 655 1017 KeyID 656 CPMKeyState::getKeyID(ULONG virtualKey, KeyButton button )1018 CPMKeyState::getKeyID(ULONG virtualKey, KeyButton button, bool numpad, USHORT usChar) 657 1019 { 658 1020 LOG((CLOG_DEBUG "getKeyID:")); 659 // if ((button & 0x100u) != 0) { 660 // virtualKey += 0x100u; 661 // } 662 // return s_virtualKey[virtualKey]; 663 return virtualKey < sizeof(s_virtualKey) / sizeof(s_virtualKey[0]) 664 ? s_virtualKey[virtualKey] 665 : kKeyNone; 1021 if (virtualKey < sizeof(s_virtualKey) / sizeof(s_virtualKey[0])) { 1022 1023 // 1024 // Numpad kludge. 1025 // 1026 if (numpad && s_virtualKey[virtualKey].numpad) { 1027 switch (usChar) { 1028 case '=': return kKeyKP_Equal; 1029 case '*': return kKeyKP_Multiply; 1030 case '+': return kKeyKP_Add; 1031 //case ',': 1032 //case '.': return kKeyKP_Separator ? kKeyKP_Decimal; 1033 case '-': return kKeyKP_Subtract; 1034 case '/': return kKeyKP_Divide; 1035 case '0': return kKeyKP_0; 1036 case '1': return kKeyKP_1; 1037 case '2': return kKeyKP_2; 1038 case '3': return kKeyKP_3; 1039 case '4': return kKeyKP_4; 1040 case '5': return kKeyKP_5; 1041 case '6': return kKeyKP_6; 1042 case '7': return kKeyKP_7; 1043 case '8': return kKeyKP_8; 1044 case '9': return kKeyKP_9; 1045 case ' ': return kKeyKP_Space; 1046 } 1047 switch (s_virtualKey[virtualKey].key) { 1048 case kKeyHome: return kKeyKP_Home; 1049 case kKeyLeft: return kKeyKP_Left; 1050 case kKeyUp: return kKeyKP_Up; 1051 case kKeyRight: return kKeyKP_Right; 1052 case kKeyDown: return kKeyKP_Down; 1053 case kKeyPageUp: return kKeyKP_PageUp; 1054 case kKeyPageDown: return kKeyKP_PageDown; 1055 case kKeyEnd: return kKeyKP_End; 1056 case kKeyBegin: return kKeyKP_Begin; 1057 case kKeyInsert: return kKeyKP_Insert; 1058 case kKeyDelete: return kKeyKP_Delete; 1059 } 1060 } else { 1061 // 1062 // Left/right shift and control kludge. 1063 // 1064 switch (virtualKey) { 1065 case VK_CTRL: 1066 if (m_virtualKeyToButton[VK_CTRL] != button) { 1067 return kKeyControl_R; 1068 } 1069 break; 1070 case VK_SHIFT: 1071 if (m_virtualKeyToButton[VK_SHIFT] != button) { 1072 return kKeyShift_R; 1073 } 1074 break; 1075 } 1076 } 1077 return s_virtualKey[virtualKey].key; 1078 } 1079 return kKeyNone; 666 1080 } 667 1081 … … 700 1114 } 701 1115 1116 static const char * 1117 getKeyName(KeyID key) 1118 { 1119 const KeyNameMapEntry *entry = &kKeyNameMap[0]; 1120 while (entry->m_id != kKeyNone) { 1121 if (entry->m_id == key) { 1122 return entry->m_name; 1123 } 1124 entry++; 1125 } 1126 /* ASCII? */ 1127 static char s_buf[2][2]; 1128 static char s_idxBuf; 1129 if (key >= ' ' && key <= 'z') { 1130 char *buf = &s_buf[s_idxBuf = (s_idxBuf + 1) % 2][0]; 1131 *buf = key; 1132 return buf; 1133 } 1134 return ""; 1135 } 1136 702 1137 void 703 1138 CPMKeyState::addKeyEntry(CKeyMap& keyMap, CKeyMap::KeyItem& item) 704 1139 { 705 LOG((CLOG_DEBUG "addKeyEntry:")); 706 keyMap.addKeyEntry(item); 1140 ClientData data; data.u = item.m_client; assert(sizeof(data.u) == sizeof(data)); 1141 LOG((CLOG_DEBUG 1142 "addKeyEntry: scan=%02x+%02x req=%c%c%c%c%c%c[%c%c%c%c%c%c]{%x} id=%04x(%c) xlatChar=%02x(%c) scan=%02x xlatScan=%02x [%s]%s%s%s%s%s%s", 1143 item.m_button, convertKeyModiferMaskToTCF(item.m_required), 1144 item.m_required & KeyModifierShift ? 'S' : '-', 1145 item.m_required & KeyModifierControl ? 'C' : '-', 1146 item.m_required & KeyModifierAlt ? 'A' : '-', 1147 item.m_required & KeyModifierAltGr ? 'R' : '-', 1148 item.m_required & KeyModifierCapsLock ? 'U' : '-', 1149 item.m_required & KeyModifierNumLock ? 'N' : '-', 1150 item.m_sensitive & KeyModifierShift ? 'S' : '-', 1151 item.m_sensitive & KeyModifierControl ? 'C' : '-', 1152 item.m_sensitive & KeyModifierAlt ? 'A' : '-', 1153 item.m_sensitive & KeyModifierAltGr ? 'R' : '-', 1154 item.m_sensitive & KeyModifierCapsLock ? 'U' : '-', 1155 item.m_sensitive & KeyModifierNumLock ? 'N' : '-', 1156 item.m_generates, 1157 item.m_id, item.m_id < 128 && isprint(item.m_id) ? item.m_id : '.', 1158 data.s.xlatChar, data.s.xlatChar < 128 && isprint(data.s.xlatChar) ? data.s.xlatChar : '.', 1159 data.s.scan, data.s.xlatScan, 1160 getKeyName(item.m_id), 1161 data.s.fExtendedKey ? " extendedkey" : "", 1162 data.s.fShiftKey ? " shiftkey" : "", 1163 data.s.fDeadKey ? " deadkey" : "", 1164 data.s.fComposite ? " composite" : "", 1165 item.m_lock ? " lock" : "", 1166 item.m_dead ? " dead" : "" 1167 )); 1168 if (data.s.scan2 || data.s.xlatScan2) { 1169 LOG((CLOG_DEBUG 1170 "addKeyEntry: xlatChar2=%02x(%c) scan2=%02x xlatScan2=%02x", 1171 data.s.xlatChar2, data.s.xlatChar2 < 128 && isprint(data.s.xlatChar2) ? data.s.xlatChar2 : '.', 1172 data.s.scan2, data.s.xlatScan2)); 1173 } 1174 1175 if (!keyMap.addKeyEntry(item)) { 1176 LOG((CLOG_DEBUG "!not accepted!")); 1177 } 707 1178 if (item.m_group == 0) { 708 1179 m_keyToVKMap[item.m_id] = item.m_client;
Note:
See TracChangeset
for help on using the changeset viewer.