keypress.cpp

Go to the documentation of this file.
00001 // $Id: keypress.cpp 1361 2006-06-25 16:43:38Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // Implementation of the KeyPress class that encapsulates key presses in camelot.
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "keypress.h"
00105 #include "vkextra.h"
00106 #include "camelot.h"
00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "hotkeys.h"
00109 #include "keymsg.h"
00110 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "ctrlhelp.h"
00113 //#include "basebar.h"
00114 //#include "dragmgr.h"
00115 #include "unicdman.h"
00116 
00117 DECLARE_SOURCE("$Revision: 1361 $");
00118 
00119 CC_IMPLEMENT_MEMDUMP(KeyPressSysMsg,CC_CLASS_MEMDUMP)
00120 CC_IMPLEMENT_MEMDUMP(KeyPress,      CC_CLASS_MEMDUMP)
00121 
00122 CC_IMPLEMENT_DYNAMIC(KeyMsg,Msg)
00123 
00124 // This will get Camelot to display the filename and linenumber of any memory allocations
00125 // that are not released at program exit
00126 #define new CAM_DEBUG_NEW
00127 
00128 struct ExtraUnicode
00129 {
00130     UINT32  VirtKey;
00131     WCHAR   Unicode;
00132 } ExtraUnicodes[] = 
00133 {
00134     {CAMKEY(F1),        CAMELOT_UNICODE_BASE + 0},
00135     {CAMKEY(F2),        CAMELOT_UNICODE_BASE + 1},
00136     {CAMKEY(F3),        CAMELOT_UNICODE_BASE + 2},
00137     {CAMKEY(F4),        CAMELOT_UNICODE_BASE + 3},
00138     {CAMKEY(F5),        CAMELOT_UNICODE_BASE + 4},
00139     {CAMKEY(F6),        CAMELOT_UNICODE_BASE + 5},
00140     {CAMKEY(F7),        CAMELOT_UNICODE_BASE + 6},
00141     {CAMKEY(F8),        CAMELOT_UNICODE_BASE + 7},
00142     {CAMKEY(F9),        CAMELOT_UNICODE_BASE + 8},
00143     {CAMKEY(F10),       CAMELOT_UNICODE_BASE + 9},
00144     {CAMKEY(F11),       CAMELOT_UNICODE_BASE + 10},
00145     {CAMKEY(F12),       CAMELOT_UNICODE_BASE + 11},
00146     {CAMKEY(F13),       CAMELOT_UNICODE_BASE + 12},
00147     {CAMKEY(F14),       CAMELOT_UNICODE_BASE + 13},
00148     {CAMKEY(F15),       CAMELOT_UNICODE_BASE + 14},
00149     {CAMKEY(F16),       CAMELOT_UNICODE_BASE + 15},
00150     {CAMKEY(F17),       CAMELOT_UNICODE_BASE + 16},
00151     {CAMKEY(F18),       CAMELOT_UNICODE_BASE + 17},
00152     {CAMKEY(F19),       CAMELOT_UNICODE_BASE + 18},
00153     {CAMKEY(F20),       CAMELOT_UNICODE_BASE + 19},
00154     {CAMKEY(F21),       CAMELOT_UNICODE_BASE + 20},
00155     {CAMKEY(F22),       CAMELOT_UNICODE_BASE + 21},
00156     {CAMKEY(F23),       CAMELOT_UNICODE_BASE + 22},
00157     {CAMKEY(F24),       CAMELOT_UNICODE_BASE + 23},
00158 
00159     {CAMKEY(SHIFT),     CAMELOT_UNICODE_BASE + 24},
00160     {CAMKEY(CONTROL),   CAMELOT_UNICODE_BASE + 25},
00161     {CAMKEY(MENU),      CAMELOT_UNICODE_BASE + 26},
00162 
00163     {CAMKEY(DELETE),    CAMELOT_UNICODE_BASE + 28},
00164     {CAMKEY(NUMPAD_DELETE), CAMELOT_UNICODE_BASE + 28},
00165     {CAMKEY(INSERT),    CAMELOT_UNICODE_BASE + 27},
00166     {CAMKEY(HOME),      CAMELOT_UNICODE_BASE + 29},
00167     {CAMKEY(END),       CAMELOT_UNICODE_BASE + 30},
00168     {CAMKEY(PRIOR),     CAMELOT_UNICODE_BASE + 31},     // Page up
00169     {CAMKEY(NEXT),      CAMELOT_UNICODE_BASE + 32},     // Page down
00170 
00171     {CAMKEY(LEFT),      CAMELOT_UNICODE_BASE + 33},     // Cursor left
00172     {CAMKEY(UP),        CAMELOT_UNICODE_BASE + 34},     // Cursor up
00173     {CAMKEY(RIGHT),     CAMELOT_UNICODE_BASE + 35},     // Cursor right
00174     {CAMKEY(DOWN),      CAMELOT_UNICODE_BASE + 36},     // Cursor down
00175 
00176     {CAMKEY(NUMLOCK),       CAMELOT_UNICODE_BASE + 37},
00177     {CAMKEY(SCROLL),    CAMELOT_UNICODE_BASE + 38},
00178     {CAMKEY(CAPITAL),       CAMELOT_UNICODE_BASE + 39},
00179 
00180     {CAMKEY(ESCAPE),    CAMELOT_UNICODE_BASE + 40},
00181     {CAMKEY(CANCEL),    CAMELOT_UNICODE_BASE + 41},     // Ctrl-break
00182 
00183     {CAMKEY(PAUSE),         CAMELOT_UNICODE_BASE + 42},
00184     {CAMKEY(SELECT),    CAMELOT_UNICODE_BASE + 43},
00185     {CAMKEY(EXECUTE),   CAMELOT_UNICODE_BASE + 44},
00186     {CAMKEY(SNAPSHOT),  CAMELOT_UNICODE_BASE + 45},     // Print screen
00187     {CAMKEY(HELP),      CAMELOT_UNICODE_BASE + 46},
00188 
00189     {CAMKEY(MINUS),     CAMELOT_UNICODE_BASE + 47},     // These two are placed in hear so that when you do ctrl+<key>
00190     {CAMKEY(EQUALS),        CAMELOT_UNICODE_BASE + 48},     // a unicode value will be generated, allowing the keypress to be made
00191 
00192     {CAMKEY(1),         CAMELOT_UNICODE_BASE + 49},
00193     {CAMKEY(2),         CAMELOT_UNICODE_BASE + 50},
00194     {CAMKEY(3),         CAMELOT_UNICODE_BASE + 51},
00195     {CAMKEY(4),         CAMELOT_UNICODE_BASE + 52},
00196     {CAMKEY(5),         CAMELOT_UNICODE_BASE + 53},
00197 
00198     {CAMKEY(ADD),       CAMELOT_UNICODE_BASE + 54},
00199     {CAMKEY(SUBTRACT),  CAMELOT_UNICODE_BASE + 55},
00200 
00201     {CAMKEY(0),         CAMELOT_UNICODE_BASE + 56},
00202     {CAMKEY(9),         CAMELOT_UNICODE_BASE + 57},
00203     {CAMKEY(8),         CAMELOT_UNICODE_BASE + 58},
00204     {CAMKEY(7),         CAMELOT_UNICODE_BASE + 59},
00205 
00206     {CAMKEY(NUMPAD_ADD), _T('+')},                      // These are need so we can get unicode version, and 
00207     {CAMKEY(NUMPAD_SUBTRACT), _T('-')},                 // hence get the hotkey handled
00208 
00209     {CAMKEY(CC_NONE), 0}    // Marks the end of the list
00210 };
00211 
00212 // The static member vars of KeyPress that will hold the current state of the modifier keys
00213 BOOL KeyPress::AdjustStateLeft          = FALSE;
00214 BOOL KeyPress::AdjustStateRight         = FALSE;
00215 BOOL KeyPress::ConstrainStateLeft       = FALSE;
00216 BOOL KeyPress::ConstrainStateRight      = FALSE;
00217 BOOL KeyPress::AlternativeStateLeft     = FALSE;
00218 BOOL KeyPress::AlternativeStateRight    = FALSE;
00219 BOOL KeyPress::OptionStateLeft          = FALSE;
00220 BOOL KeyPress::OptionStateRight         = FALSE;
00221 
00222 // TRUE if one or more modifier keys changed on the last key event
00223 BOOL KeyPress::fModifierChanged = FALSE;
00224 
00225 // Ascii generating vars used with Alt and numerical key presses
00226 INT32 KeyPress::AsciiVal = -1;
00227 BOOL KeyPress::ValidAsciiVal = FALSE;
00228 
00229 BYTE KeyPress::LastLeadByte = 0;
00230 
00231 // This was done by Tim
00232 // this macro returns TRUE if the machine does not support every key, which means
00233 // WinNT or not, basically
00234 #if WIN32
00235 #define INCOMPLETE_KEYS IsWin32s()
00236 #else
00237 #define INCOMPLETE_KEYS TRUE
00238 #endif
00239             
00240 extern void Beep();
00241 
00242 List                    KeyPress::AdditionalVirtKeys;
00243 UINT32                  KeyPressSysMsg::m_LastVirtKey = 0;
00244 
00245 /********************************************************************************************
00246 
00247 > KeyPressSysMsg::KeyPressSysMsg(MSG* pMsg)
00248 
00249     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00250     Created:    26/8/94
00251     Inputs:     pMsg = Ptr to a Windows message block
00252     Outputs:    -
00253     Returns:    -
00254     Purpose:    The constructor.
00255                 Creates a key press message object from a raw Windows message block.
00256                 A valid KeyPressSysMsg is constructed if the message was one of these:
00257                     WM_KEYDOWN
00258                     WM_KEYUP
00259                     WM_SYSKEYDOWN
00260                     WM_SYSKEYUP
00261                     WM_CHAR
00262 
00263     Errors:     If the Windows message is not key-related, then the member function IsValid()
00264                 will return FALSE
00265     SeeAlso:    KeyPressSysMsg::IsValid
00266 
00267 ********************************************************************************************/
00268 
00269 KeyPressSysMsg::KeyPressSysMsg(wxKeyEvent* pMsg)
00270 {
00271     // Assume the message is a key-related one that we want
00272     Valid = TRUE;
00273 
00274     // There doesn't seem to be a need to distinguish between WM_KEY and WM_SYSKEY message
00275     // so map them to the same KM message
00276     if( wxEVT_KEY_DOWN == pMsg->GetEventType() ) 
00277     {
00278         Message = KM_KEYDOWN;
00279     }
00280     else
00281     if( wxEVT_CHAR == pMsg->GetEventType() ) 
00282     {
00283         Message = KM_CHAR;
00284     }
00285     else
00286     if( wxEVT_KEY_UP == pMsg->GetEventType() ) 
00287     {
00288         Message = KM_KEYUP;
00289     }
00290 PORTNOTE("other", "Removed Windows IME usage" )
00291 #ifndef EXCLUDE_FROM_XARALX
00292     case WM_IME_CHAR:
00293         TRACE( _T("IME\n"));
00294         break;
00295 #endif
00296     else
00297     {
00298         // Message was not one we're interested in, so the KeyPressSysMsg object is invalid
00299         Valid = FALSE;
00300     }
00301 
00302     if (Valid)
00303     {
00304         // Now we have a valid Windows message to play with.
00305         // Extract the data and store in a more platform-indy way
00306 
00307         // Get the virtual key code for the key pressed
00308         VirtKey = pMsg->GetKeyCode();
00309 
00310         // Get the key data flags word
00311 //      INT32 KeyData = pMsg->lParam;
00312         
00313         // We NEVER want to intercept Alt-Tab events, so filter them out here
00314         // (N.B. This was only ever a problem on Win16 - NT doesn't send us
00315         // Alt-Tab keydown events, only key-ups, which are ignored.)
00316         if ((VirtKey == CAMKEY(TAB)) && KeyPress::IsAlternativePressed())
00317         {
00318             Valid=FALSE;
00319             return;
00320         }
00321         
00322 PORTNOTE("other", "Removed some keypress mangling" )
00323 #ifndef EXCLUDE_FROM_XARALX
00324         RepeatCount = KeyData & 0xffff;
00325         ScanCode    = (KeyData >> 16) & 0xff;
00326         Extended    = (KeyData & (1<<24)) != 0;
00327         PrevDown    = (KeyData & (1<<30)) != 0;
00328 #else
00329         RepeatCount = 1;
00330         ScanCode    = VirtKey;
00331         Extended    = VirtKey >= WXK_START;
00332         PrevDown    = m_LastVirtKey == VirtKey;
00333 #if FALSE != wxUSE_UNICODE
00334         m_Char      = pMsg->GetUnicodeKey();
00335         TRACEUSER( "jlh92", _T("m_Char = %04x Ext=%d\n"), m_Char, Extended );
00336 #endif
00337 #endif
00338         // Update the last virtual keycode if not a modifier
00339         switch( VirtKey )
00340         {
00341         case WXK_SHIFT:
00342         case WXK_ALT:
00343         case WXK_CONTROL:
00344         case WXK_MENU:
00345             // Skip
00346             break;
00347 
00348         default:
00349             if( KM_KEYUP == Message )
00350                 m_LastVirtKey = 0;
00351             else
00352                 m_LastVirtKey = VirtKey;
00353             break;
00354         }
00355     }
00356 }
00357 
00358 /********************************************************************************************
00359 
00360 > BOOL KeyPressSysMsg::IsValid()
00361 
00362     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00363     Created:    26/8/94
00364     Inputs:     -
00365     Outputs:    -
00366     Returns:    TRUE if the KeyPressSysMsg object is a valid one. FALSE otherwise
00367     Purpose:    Allows you to see if the KeyPressSysMsg was legally constructed.
00368     Errors:     -
00369     SeeAlso:    KeyPressSysMsg::KeyPressSysMsg
00370 
00371 ********************************************************************************************/
00372 
00373 BOOL KeyPressSysMsg::IsValid()
00374 {
00375     return Valid;
00376 }
00377 
00378 //-------------------------------------------------------------------------------------------
00379 //-------------------------------------------------------------------------------------------
00380 //-------------------------------------------------------------------------------------------
00381 //-------------------------------------------------------------------------------------------
00382 
00383 /********************************************************************************************
00384 
00385 > static BOOL KeyPress::Init()
00386 
00387     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00388     Created:    26/8/94
00389     Inputs:     -
00390     Outputs:    -
00391     Returns:    TRUE if initialised correctly
00392     Purpose:    Initialises the KeyPress class
00393     Errors:     -
00394     SeeAlso:    KeyPress::IsValid, KeyPress::GenerateKeyPress
00395 
00396 ********************************************************************************************/
00397 
00398 // remove after testing
00399 #include "hotkeys.h"
00400 
00401 BOOL KeyPress::Init()
00402 {
00403     return TRUE;
00404 }
00405 
00406 
00407 
00408 /********************************************************************************************
00409 
00410 > static FilePath KeyPress::GetHotKeysFilename()
00411 
00412     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00413     Created:    8/Jun/2006
00414     Inputs:     -
00415     Outputs:    -
00416     Returns:    PathName reference to location of hotkeys config file
00417     Purpose:    
00418 
00419 ********************************************************************************************/
00420 
00421 FilePath KeyPress::GetHotKeysFilename()
00422 {
00423     FilePath result;
00424 
00425     wxStandardPaths     Paths;
00426     wxString    strPath( Paths.GetUserConfigDir() );
00427     strPath += _T("/.xaralx/hotkeys");
00428 
00429     if (wxFile::Exists(strPath))
00430         result.SetPathName(strPath, FALSE);
00431 
00432     return result;
00433 }
00434 
00435 
00436 
00437 /********************************************************************************************
00438 >   static BOOL KeyPress::DispatchKeyEvent(UINT32 nMsgID, UINT32 nChar, UINT32 nRepCnt, UINT32 nFlags)
00439 
00440     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00441     Created:    7/10/94
00442     Inputs:     nMsgID      the Windows ID of the key message, eg. WM_KEYDOWN
00443                 nChar       the virtual key code / char value (depending on you believe)
00444                 nRepCnt     repeat count
00445                 nFlags      keyboard state flags, eg. key down or up
00446     Outputs:    -
00447     Returns:    TRUE if the app processed the event.
00448     Purpose:    Packages an MFC key-stroke message into a form suitable for the kernel
00449                 and calls the keyboard system with the event.
00450     Errors:     -
00451     SeeAlso:    KeyPress::TranslateMessage
00452 ********************************************************************************************/
00453 
00454 BOOL KeyPress::DispatchKeyEvent(UINT32 nMsgID, UINT32 nChar, UINT32 nRepCnt, UINT32 nFlags)
00455 {
00456     // Make sure the kernel knows which view/doc the event applies to, if any.
00457     if (Document::GetSelected() != NULL) Document::GetSelected()->SetCurrent();
00458     if (DocView::GetSelected() != NULL)  DocView::GetSelected()->SetCurrent();
00459 
00460 PORTNOTETRACE("other,", "BaseTextClass::PreOpProcessing - do nothing" );
00461 #ifndef EXCLUDE_FROM_XARALX
00462     // For compatibility with existing code we must repackage the unpacked message.
00463     // NB. the RHS of the lParam expression will work for Win16 as well.
00464     MSG msg;
00465     msg.message = nMsgID;
00466     msg.wParam  = nChar;
00467     msg.lParam  = (nRepCnt & 0xFFFF) | ((((LPARAM) nFlags) & 0xFFFF) << 16);
00468     
00469     // Call the key-press system.
00470     return TranslateMessage(&msg);
00471 #else
00472     return true;
00473 #endif
00474 }
00475 
00476 
00477 
00478 /********************************************************************************************
00479 
00480 > KeyPress::KeyPress()
00481 
00482     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00483     Created:    24/8/94
00484     Inputs:     -
00485     Outputs:    -
00486     Returns:    -
00487     Purpose:    Default constructor.
00488                 Creates an invalid keypress object.  The KeyPress class will have one or more public
00489                 constructors or static member functions for creating valid KeyPress objects.
00490     Errors:     -
00491     SeeAlso:    KeyPress::IsValid, KeyPress::GenerateKeyPress
00492 
00493 ********************************************************************************************/
00494 
00495 KeyPress::KeyPress()
00496 {
00497     Initialise();
00498 }
00499 
00500 /********************************************************************************************
00501 
00502 > KeyPress::KeyPress(KeyPressSysMsg* pKeySysMsg,WCHAR UnicodeChar)
00503 
00504     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00505     Created:    26/8/94
00506     Inputs:     pKeySysMsg  = Ptr to a platform indepenent version of a Windows key press message
00507                 UnicodeChar = The Unicode char this key press should have
00508     Outputs:    -
00509     Returns:    -
00510     Purpose:    Constructs a KeyPress object from the given parameters
00511     Errors:     -
00512     SeeAlso:    KeyPress::IsValid, KeyPress::GenerateKeyPress
00513 
00514 ********************************************************************************************/
00515 
00516 KeyPress::KeyPress(KeyPressSysMsg* pKeySysMsg,WCHAR UnicodeChar)
00517 {
00518     VirtKey     = pKeySysMsg->VirtKey;
00519     Unicode     = UnicodeChar;
00520 
00521     Adjust      = KeyPress::AdjustStateLeft      | KeyPress::AdjustStateRight;
00522     Constrain   = KeyPress::ConstrainStateLeft   | KeyPress::ConstrainStateRight;
00523     Alternative = KeyPress::AlternativeStateLeft | KeyPress::AlternativeStateRight;
00524     Option      = KeyPress::OptionStateLeft      | KeyPress::OptionStateRight;
00525 
00526     Extended    = pKeySysMsg->Extended;
00527 
00528     // Interpret Alt+Ctrl as Extended Alt, because AltGr (UK right hand Alt) produces an additional 
00529     // Ctrl key press that is indistinguishable from a left hand Ctrl.
00530     // This means that left hand Alt+Ctrl will appear the same as right hand AltGr to Camelot.
00531     // E.g. Alt+Ctrl+Spacebar == AltGr+Spacebar
00532     if (Alternative && Constrain)
00533     {
00534         Extended  = TRUE;
00535         Constrain = FALSE;
00536     }
00537 
00538     Repeat      = pKeySysMsg->PrevDown;
00539     RightHand   = pKeySysMsg->Extended;
00540     Release     = (pKeySysMsg->Message == KM_KEYUP);
00541     m_fIsChar   = (pKeySysMsg->Message == KM_CHAR);
00542 
00543     Valid       = TRUE;     // This is now a valid KeyPress object.
00544 }
00545 
00546 /********************************************************************************************
00547 
00548 > KeyPress::KeyPress(   UINT32 ThisVirtKey,
00549                         BOOL PlusAdjust      = FALSE, 
00550                         BOOL PlusConstrain   = FALSE, 
00551                         BOOL PlusAlternative = FALSE,
00552                         BOOL ExtendedKey     = FALSE)
00553 
00554     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00555     Created:    30/8/94
00556     Inputs:     ThisVirtKey      = The virtual key code of the key you want to use
00557                 PlusAdjust       = TRUE if the key should be modified by the Adjust key
00558                 PlusConstrain    = TRUE if the key should be modified by the Constrain key
00559                 PlusAlternative  = TRUE if the key should be modified by the Alternative key
00560                 ExtendedKey      = TRUE if you are specifying an extended key (e.g. "Enter" key instead of "Return")
00561                 WorksInDragsKey  = TRUE if you want this keypress to work in the middle of drags.
00562     Outputs:    -
00563     Returns:    -
00564     Purpose:    Constructs a KeyPress object from the given parameters
00565                 This constructor is for use by systems that deal with "hot keys", i.e. ones that are only
00566                 interested in the physical key that is being pressed
00567     Errors:     -
00568     SeeAlso:    KeyPress::IsValid, KeyPress::GenerateKeyPress
00569 
00570 ********************************************************************************************/
00571 
00572 KeyPress::KeyPress(UINT32 ThisVirtKey, BOOL PlusAdjust, BOOL PlusConstrain, BOOL PlusAlternative, BOOL ExtendedKey,
00573                     BOOL WorksInDragsKey)
00574 {
00575     Initialise();
00576 
00577     VirtKey     = ThisVirtKey;
00578     Adjust      = PlusAdjust;
00579     Constrain   = PlusConstrain;
00580     Alternative = PlusAlternative;
00581     Extended    = ExtendedKey;
00582     WorksInDrag = WorksInDragsKey;
00583     Valid       = TRUE;
00584 }
00585 
00586 
00587 
00588 /********************************************************************************************
00589 
00590 >   static KeyPress* ConstructVK(TCHAR ch);
00591 
00592     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00593     Created:    11/10/95
00594     Inputs:     ch - ASCII/Unicode value of required keypress
00595     Outputs:    -
00596     Returns:    -
00597     Purpose:    Constructs a keypress that represents the keypress required to generate the
00598                 specified character.  The Virtual Code will be CAMKEY(CC_NONE) if the key cannot
00599                 be generated
00600     Errors:     -
00601     SeeAlso:    -
00602 
00603 ********************************************************************************************/
00604 KeyPress* KeyPress::ConstructVK(TCHAR ch)
00605 {
00606 //  PORTNOTETRACE( "other", "KeyPress::ConstructVK - do nothing" );
00607     KeyPress* pNew = new KeyPress();
00608 
00609 #if !defined(EXCLUDE_FROM_XARALX)
00610     if (pNew != NULL)
00611     {
00612         INT8 Result = ::VkKeyScan(ch);
00613         BYTE LowByte = Result & 0xFF;
00614         BYTE HighByte = (Result >> 8) & 0xFF;
00615 
00616         if ((HighByte == 0xFF) && (LowByte == 0xFF))
00617         {
00618             pNew->VirtKey = CAMKEY(CC_NONE);
00619         }
00620         else
00621         {
00622             pNew->VirtKey = LowByte;
00623             pNew->Adjust = HighByte & 1;
00624             pNew->Constrain = HighByte & 2;
00625             pNew->Alternative   = HighByte & 4;
00626         }
00627     }
00628 #endif
00629     
00630     return pNew;
00631 }
00632 
00633 
00634 
00635 /********************************************************************************************
00636 
00637 >   KeyPress::Initialise()
00638 
00639     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00640     Created:    11/10/96
00641     Inputs:     -
00642     Outputs:    See below
00643     Returns:    -
00644     Purpose:    Initialises all member variables of the KeyPress object to sensible values
00645     Errors:     -
00646     SeeAlso:    KeyPress constructors
00647 
00648 ********************************************************************************************/
00649 void KeyPress::Initialise()
00650 {
00651     // Some highly unlikely Unicode char
00652     Unicode     = 0xffff;
00653 
00654     // A highly unlikely virtual key
00655     VirtKey     = CAMKEY(CC_NONE);
00656 
00657     // Set all the flags to FALSE
00658     Adjust      = FALSE;
00659     Constrain   = FALSE;
00660     Alternative = FALSE;
00661     Option      = FALSE;
00662 
00663     Extended    = FALSE;
00664 
00665     Repeat      = FALSE;
00666     RightHand   = FALSE;
00667     Release     = FALSE;
00668     m_fIsChar   = FALSE;
00669 
00670     // This is an invalid KeyPress object at the moment
00671     Valid       = FALSE;
00672 }
00673 
00674 
00675 
00676 /********************************************************************************************
00677 
00678 > BOOL KeyPress::IsValid()
00679 
00680     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00681     Created:    26/8/94
00682     Inputs:     -
00683     Outputs:    -
00684     Returns:    TRUE if the KeyPress object is a valid one. FALSE otherwise
00685     Purpose:    Allows you to see if the KeyPress is legal.
00686                 The default KeyPress constuctor will always create invalid instances. It is up
00687                 to other constructors, or member functions, to generate valid ones
00688     Errors:     -
00689     SeeAlso:    KeyPress::KeyPress, KeyPress::GenerateKeyPress
00690 
00691 ********************************************************************************************/
00692 
00693 BOOL KeyPress::IsValid()
00694 {
00695     return Valid;
00696 }
00697 
00698 /********************************************************************************************
00699 
00700 > static BOOL KeyPress::IsModifier(UINT32 VirtKey)
00701 
00702     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00703     Created:    26/8/94
00704     Inputs:     VirtKey = A Windows virtual key code
00705     Outputs:    -
00706     Returns:    TRUE  if the key is one of the modifier keys
00707                 FALSE otherwise
00708     Purpose:    Central modifier key identifying routine.
00709                 The modifiers are as follows :
00710                     Both Alt   keys
00711                     Both Shift keys
00712                     Both Ctrl  keys
00713     Errors:     -
00714     SeeAlso:    -
00715 
00716 ********************************************************************************************/
00717 
00718 BOOL KeyPress::IsModifier(UINT32 VirtKey)
00719 {
00720     return (VirtKey == CAMKEY(CC_MOD_ADJUST) || VirtKey == WXK_CC_MOD_CONSTRAIN || VirtKey == WXK_CC_MOD_ALTERNATIVE);
00721 }
00722 
00723 /********************************************************************************************
00724 
00725  > static INT32 KeyPress::GenerateUnicode(UINT32 VirtKey,UINT32 ScanCode,BYTE* pKeyState,WCHAR* pWideCharBuf,INT32 WideCharBufSize)
00726 
00727     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00728     Created:    25/8/94
00729     Inputs:     VirtKey         = a Windows virtual key code
00730                 ScanCode        = the scan code generated by the keyboard
00731                 pKeyState       = 256 byte array filled with the current keyboard state via GetKeyboardState
00732                 pWideCharBuf    = buffer to stick the Unicode char(s) into
00733                 WideCharBufSize = the size of the wide char buffer (min value of 2)
00734     Outputs:    pWideCharBuf will contain 1 WCHAR at index [0]
00735     Returns:    The number of Unicode chars generated (see the Windows ToUnicode() function)
00736     Purpose:    Converts a virtual key code into a Unicode char.
00737                 This is a layer on top of the Windows ToUnicode() function that will generate Unicodes in the
00738                 corporate user zone for keys that do not have a standard Unicode evivalent (e.g. function keys)
00739 
00740                 If the internal call to ToUnicode() fails, but the VirtKey is an alphabetic key, a Unicode code is 
00741                 generated that is equivalent to pressing Ctrl+<alphabetic key>, e.g. Ctrl+A = 1, Ctrl+B = 2.
00742                 This happens when you press Ctrl+Alt+<alphabetic key>, which is only really used by the hot key system,
00743                 so therefore the actual unicode code is not significant (correct at time of writing - Markn 11/1/95)
00744     Errors:     -
00745     SeeAlso:    KeyPress::IsValid
00746 
00747 ********************************************************************************************/
00748 
00749 INT32 KeyPress::GenerateUnicode(UINT32 VirtKey,UINT32 ScanCode,BYTE* pKeyState,WCHAR* pWideCharBuf,UINT32 WideCharBufSize)
00750 {
00751 #if defined(__WXMSW__)
00752     // Make sure we have a buffer to use
00753     ENSURE(WideCharBufSize >= 2,"The wide char buffer size should be at least 2");
00754     if (WideCharBufSize < 2) return 0;
00755 
00756     INT32 NumChars = ToUnicode(VirtKey,ScanCode,pKeyState,pWideCharBuf,WideCharBufSize,0);
00757 
00758     // NumChars == 0 if ToUnicode() failed to generate a code for the keypress
00759 
00760     // If no direct eqivalent Unicode char, see if we can generate one with the ASCII value for the VirtKey
00761     // or look one up in our extra Unicode table
00762     if (NumChars == 0)
00763     {
00764         WORD pWordBuf[10];
00765 
00766         // See if ToAscii() can make a Latin I ASCII char out of it
00767         INT32 NumASCIIChars = ToAscii(VirtKey,ScanCode,pKeyState,pWordBuf,0);
00768 
00769         if (NumASCIIChars == 1)
00770         {
00771             // Map the lower byte ASCII value onto the equivalent Unicode char
00772             pWideCharBuf[0] = pWordBuf[0] & 0xff;
00773             NumChars = 1;
00774         }
00775     }
00776 
00777     if (NumChars == 0)
00778     {
00779         // ToAscii() failed, so lets have a look in our table
00780 
00781         INT32 i=0;
00782         BOOL finished = FALSE;
00783 
00784         do
00785         {
00786             // We've finished if we've reached the ungeneratable VK code
00787             finished = (ExtraUnicodes[i].VirtKey == CAMKEY(CC_NONE));
00788 
00789             if (!finished && ExtraUnicodes[i].VirtKey == VirtKey)
00790             {
00791                 // We have found an entry in our table for the given virtual key
00792 
00793                 // Stuff the Unicode value into the buffer and set the num chars generated to 1
00794                 pWideCharBuf[0] = ExtraUnicodes[i].Unicode;
00795                 NumChars = 1;
00796                 finished = TRUE;
00797             }
00798             i++;
00799         } while (!finished);
00800 
00801         // Check the runtime list too
00802         if (NumChars != 1)
00803         {
00804             finished = FALSE;
00805             AdditionalVirtKey* pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetHead();
00806             while (!finished && (pKey != NULL))
00807             {
00808                 if (pKey->VirtualKeyCode == VirtKey)
00809                 {
00810                     pWideCharBuf[0] = pKey->UnicodeValue;
00811                     NumChars = 1;
00812                     finished = TRUE;
00813                 }
00814 
00815                 pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetNext(pKey);
00816             }
00817         }
00818     }
00819 
00820     if (NumChars == 0)
00821     {
00822         // If the virt key is obviously one that should be handled (i.e. an alphabetical key),
00823         // we automatically generate a code.
00824         // This Unicode code will be the same as the one generated by Ctrl+<alphabetical key>
00825         //
00826         // "Why do we need this?" I hear you scream. This is because ToUnicode() fails when you do a 
00827         // Ctrl+Alt+<key>.  As this is an important modifier combo used by the hot key system, we need to make it work.
00828         //
00829         // Markn - 11/1/95
00830 
00831         if (VirtKey >= 'A' && VirtKey <= 'Z')
00832         {
00833             pWideCharBuf[0] = VirtKey - 'A';
00834             NumChars = 1;
00835         }
00836     }
00837 
00838 #ifdef _DEBUG
00839     /*
00840     if (IsUserName("MarkN") && (NumChars == 0))
00841     { 
00842         Beep();
00843         TRACE( _T("\n***\nVirtKey %lx has no Unicode equivalent!\n***\n"),VirtKey); 
00844     }
00845     */
00846 #endif
00847 
00848     // Return the number of Unicode chars that have been dumped into the buffer
00849     return NumChars;
00850 #else
00851     return 0;
00852 #endif
00853 }
00854         
00855 
00856 /********************************************************************************************
00857 
00858 > static BOOL KeyPress::IgnoreKeyMessage(KeyPressSysMsg* pKeySysMsg)
00859 
00860     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00861     Created:    25/8/94
00862     Inputs:     pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message
00863     Outputs:    -
00864     Returns:    TRUE  if the key press message should be ignored
00865                 FALSE if the key press message should be processed
00866     Purpose:    This filters out any invalid key messages that we may get from Windows, such as 
00867                 auto-repeated modifier (shift, ctrl, alt) keys.
00868     Errors:     -
00869     SeeAlso:    KeyPress::GenerateKeyPress
00870 
00871 ********************************************************************************************/
00872 
00873 BOOL KeyPress::IgnoreKeyMessage(KeyPressSysMsg* pKeySysMsg)
00874 {
00875 //  PORTNOTETRACE( "other", "KeyPress::IgnoreKeyMessage - do nothing" );
00876 
00877     ENSURE(pKeySysMsg->IsValid(),"Invalid KeyPressSysMsg given");
00878 
00879     // Ignore if it's a key down msg, and the key is a modifier, and it's an auto-repeat message
00880     BOOL Ignore = (pKeySysMsg->Message == KM_KEYDOWN && KeyPress::IsModifier(pKeySysMsg->VirtKey) && pKeySysMsg->PrevDown);
00881 
00882 #if !defined(EXCLUDE_FROM_XARALX)
00883     KeyPress* pNew = new KeyPress();
00884     if (UnicodeManager::IsDBCSOS())
00885     {
00886         // handling for DBCS characters; they roll up as two sepearte WM_CHAR messages
00887         if (!Ignore && pKeySysMsg->Message==KM_CHAR)
00888         {
00889             if (LastLeadByte==0 && IsDBCSLeadByte(pKeySysMsg->VirtKey))
00890             {
00891                 // It's a lead byte so store it away for the next message and ignore this one
00892                 TRACE( _T("Lead byte %d\n"), pKeySysMsg->VirtKey);
00893                 LastLeadByte = pKeySysMsg->VirtKey;
00894                 Ignore = TRUE;
00895             }
00896         }
00897     }
00898 #endif
00899     
00900     return Ignore;
00901 }
00902 
00903 /********************************************************************************************
00904 
00905 > static void KeyPress::UpdateModifierStatus(KeyPressSysMsg* pKeySysMsg)
00906 
00907     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00908     Created:    26/8/94
00909     Inputs:     pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message
00910     Outputs:    -
00911     Returns:    -
00912     Purpose:    If the message is a modifier key press, the static status vars for the modifier keys
00913                 in the KeyPress class are updated.
00914     Errors:     -
00915     SeeAlso:    KeyPress::GenerateKeyPress
00916 
00917 ********************************************************************************************/
00918 
00919 void KeyPress::UpdateModifierStatus(KeyPressSysMsg* pKeySysMsg)
00920 {
00921     ENSURE(pKeySysMsg->IsValid(),"Invalid KeyPressSysMsg given");
00922 
00923     // pKeySysMsg is not used at the moment
00924     // The modifier key state is read via GetKeyState()
00925 
00926     BOOL AdjL = KeyPress::AdjustStateLeft;      BOOL AdjR = KeyPress::AdjustStateRight;
00927     BOOL ConL = KeyPress::ConstrainStateLeft;   BOOL ConR = KeyPress::ConstrainStateRight;
00928     BOOL AltL = KeyPress::AlternativeStateLeft; BOOL AltR = KeyPress::AlternativeStateRight;
00929     BOOL OptL = KeyPress::OptionStateLeft;      BOOL OptR = KeyPress::OptionStateRight;
00930 
00931     KeyPress::AdjustStateLeft       = wxGetKeyState(CAMKEY(CC_MOD_ADJUST));
00932     KeyPress::AdjustStateRight      = KeyPress::AdjustStateLeft;
00933 
00934     KeyPress::ConstrainStateLeft    = wxGetKeyState(CAMKEY(CC_MOD_CONSTRAIN));
00935     KeyPress::ConstrainStateRight   = KeyPress::ConstrainStateLeft;
00936 
00937     KeyPress::AlternativeStateLeft  = wxGetKeyState(CAMKEY(CC_MOD_ALTERNATIVE));
00938     KeyPress::AlternativeStateRight = KeyPress::AlternativeStateLeft;
00939 
00940     KeyPress::OptionStateLeft       = FALSE;
00941     KeyPress::OptionStateRight      = FALSE;
00942 
00943     KeyPress::fModifierChanged =(AdjL != KeyPress::AdjustStateLeft)     || (AdjR != KeyPress::AdjustStateRight)     ||
00944                                 (ConL != KeyPress::ConstrainStateLeft)  || (ConR != KeyPress::ConstrainStateRight)  ||
00945                                 (AltL != KeyPress::AlternativeStateLeft)|| (AltR != KeyPress::AlternativeStateRight)||
00946                                 (OptL != KeyPress::OptionStateLeft)     || (OptR != KeyPress::OptionStateRight);
00947 }
00948 
00949 /********************************************************************************************
00950 
00951 > static KeyPress* KeyPress::MakeKeyPress(KeyPressSysMsg* pKeySysMsg)
00952 
00953     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00954     Created:    26/8/94
00955     Inputs:     pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message
00956     Outputs:    -
00957     Returns:    Ptr to a valid KeyPress object
00958                 OR NULL if not enough memory
00959     Purpose:    Makes a KeyPress from a KeyPressSysMsg.
00960     Errors:     -
00961     SeeAlso:    KeyPress::GenerateKeyPress,KeyPress::GenerateUnicode
00962 
00963 ********************************************************************************************/
00964 
00965 KeyPress* KeyPress::MakeKeyPress(KeyPressSysMsg* pKeySysMsg)
00966 {
00967 //  PORTNOTETRACE( "other", "KeyPress::MakeKeyPress - do nothing" );
00968     KeyPress*           pKeyPress = NULL;       // This will point to the key press object
00969 
00970     // Try and get a Unicode char to represent the key press
00971     WCHAR pWideChar[10];
00972     INT32 NumChars = 0;
00973     
00974     if (pKeySysMsg->Message == KM_CHAR)
00975     {
00976 #if FALSE != wxUSE_UNICODE
00977         NumChars = 1;
00978         pWideChar[0] = pKeySysMsg->m_Char;
00979 
00980         TRACEUSER( "jlh92", _T("Unicode = %c\n"), pKeySysMsg->m_Char );
00981 #else
00982         // If the message is a CHAR message, then we need to generate a Unicode value ourselves
00983         // using the char code (which is stored in the VirtKey field of the KeyPressSysMsg class)
00984         //
00985         // These codes are generated by holding down Alt and typing the ASCII value of a character
00986         // on the numerical key pad. The Virt key codes generated when doing this fail to produce
00987         // Uncode chars, so the key presses never get passed on.  However, if after this sequence an
00988         // ASCII char is specified (e.g. 'A' via Alt+ '6' '5') a WM_CHAR message is posted, so we need
00989         // to trap this and pass the Unicode equivalent of the ASCII char onto Camelot.
00990         //
00991         // The fake VirtKey code (CAMKEY(CC_NONE)) is specified so that the receiver of this key message
00992         // will not process it on the VirtKey code.  However, anyone interested in just the Unicode
00993         // value (e.g. the text tool) will process it successfully.
00994 
00995         TRACE( _T("Trail byte %d\n"), pKeySysMsg->VirtKey);
00996 
00997         char pants[3];
00998 
00999         if (UnicodeManager::IsDBCSOS())
01000         {
01001             // See if we have a lead byte 
01002             if (LastLeadByte != 0)
01003             {
01004                 pants[0] = LastLeadByte;
01005                 pants[1] = pKeySysMsg->VirtKey;
01006                 pants[2] = 0;
01007                 pWideChar[0] = UnicodeManager::MultiByteToUnicode(UnicodeManager::ComposeMultiBytes(LastLeadByte, pKeySysMsg->VirtKey));
01008             }
01009             else
01010             {
01011                 pants[0] = pKeySysMsg->VirtKey;
01012                 pants[1] = 0;
01013                 pWideChar[0] = pKeySysMsg->VirtKey;
01014             }
01015             LastLeadByte = 0;
01016         }
01017         else
01018         {
01019             pants[0] = pKeySysMsg->VirtKey;
01020             pants[1] = 0;
01021             pWideChar[0] = pKeySysMsg->VirtKey;
01022         }
01023 
01024         TRACE( _T("Entered character %s\n"),pants);
01025         TRACE( _T("Unicode value = %X\n"),pWideChar[0]);
01026 
01027         pKeySysMsg->VirtKey = CAMKEY(CC_NONE);
01028         NumChars = 1;
01029 #endif
01030     }
01031     else
01032     {
01033 #if FALSE != wxUSE_UNICODE
01034         NumChars = 1;
01035         pWideChar[0] = pKeySysMsg->m_Char;
01036         
01037         // We still have to try our custom translations (for VirtKey >= WXK_START)
01038         if( pKeySysMsg->VirtKey >= WXK_START )
01039         {
01040             INT32 i;
01041             for( i = 0; ExtraUnicodes[i].VirtKey != CAMKEY(CC_NONE); ++i )
01042             {
01043                 // We have found an entry in our table for the given virtual key
01044                 if( ExtraUnicodes[i].VirtKey == pKeySysMsg->VirtKey )
01045                 {
01046                     // Stuff the Unicode value into the buffer and set the num chars generated to 1
01047                     pWideChar[0] = ExtraUnicodes[i].Unicode;
01048                     break;
01049                 }
01050             }
01051             
01052             // Don't pass on unknown function keys
01053             if( ExtraUnicodes[i].VirtKey == CAMKEY(CC_NONE) )
01054                 NumChars = 0;
01055         }
01056         
01057         // Windows translates Ctrl+char to control codes, I don't think we need too. Hopefully
01058         // just using CR will be enought.
01059         if( IsConstrainPressed() )
01060             pWideChar[0] = _T('\n');
01061         
01062 #elif defined(__WXMSW__)
01063         BYTE pKeyState[256];            // Array to hold the current state of the keyboard
01064         if (GetKeyboardState(pKeyState))    // Scan the current keyboard state
01065         {
01066             NumChars = GenerateUnicode( pKeySysMsg->VirtKey, pKeySysMsg->ScanCode, pKeyState, pWideChar, 10 );
01067         }
01068 #else
01069         // This should never happen, but just in case we'll use a dumb implementation
01070         NumChars = 1;
01071         mbtowc( pWideChar, pKeySysMsg->VirtKey ); 
01072 #endif
01073     }
01074 
01075     if (NumChars == 1) // Make a KeyPress object if we have a valid associated Unicode character
01076     {
01077         // Construct a KeyPress object
01078         pKeyPress = new KeyPress(pKeySysMsg,pWideChar[0]);
01079 
01080         // If we make an invalid one, delete it and make sure we return NULL
01081         if (pKeyPress != NULL && !pKeyPress->IsValid())
01082         {
01083             delete pKeyPress;
01084             pKeyPress = NULL;
01085         }
01086     }
01087 
01088     return pKeyPress;
01089 }
01090 
01091 /********************************************************************************************
01092 
01093 > static BOOL KeyPress::GenerateKeyPress(MSG* pMsg,KeyPress** ppKeyPress)
01094 
01095     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01096     Created:    24/8/94
01097     Inputs:     pMsg = A Windows message
01098     Outputs:    *ppKeyPress = ptr to the generated KeyPress object, or NULL if not enough memory
01099     Returns:    TRUE  if the message was to do with a key press.
01100                 FALSE if the message wasn't to do with the keyboard at all & *ppKeyPress is unspecified
01101     Purpose:    Generates a legal, platform-independent key press object from the raw platform-dependent
01102                 data provided.
01103     Errors:     If the virtual key code doesn't have an equivalent Unicode value (either standard, or one that
01104                 we have allocated to it), then KeyPress::IsValid() will return FALSE.
01105     SeeAlso:    KeyPress::IsValid
01106 
01107 ********************************************************************************************/
01108 
01109 BOOL KeyPress::GenerateKeyPress(wxKeyEvent* pMsg,KeyPress** ppKeyPress)
01110 {
01111     // Ensure *ppKeyPress is valid, just in case we have to exit the function early
01112     *ppKeyPress = NULL;
01113 
01114     // Create a platform-indy key press message object
01115     KeyPressSysMsg KeySysMsg(pMsg);
01116 
01117     if (KeySysMsg.IsValid())
01118     {
01119         // If it's a key press message that we can ignore, then ignore it, pretending we have processed it
01120 
01121         if (!IgnoreKeyMessage(&KeySysMsg))
01122         {
01123             // We like the look of this key press event
01124 
01125             // Ensure the modifier key states are up to date
01126             UpdateModifierStatus(&KeySysMsg);
01127 
01128             // Make a KeyPress object
01129             *ppKeyPress = MakeKeyPress(&KeySysMsg);
01130 
01131             // If the mods have changed, and we were able to make a keypress object, send
01132             // a "modifiers have changed message"
01133             if (KeyPress::fModifierChanged && *ppKeyPress != NULL)
01134             {
01135                 BROADCAST_TO_ALL(KeyMsg(KeyMsg::MODIFIERCHANGED,*ppKeyPress));
01136             }
01137         }
01138 
01139 #ifdef _DEBUG
01140 /*
01141         if (*ppKeyPress != NULL)
01142         {
01143             char s[1000];
01144             _stprintf(s,"Mess = %d, Virtkey = 0x%lx, Ext = %d, PrevD = %d, Shift = %d, Ctrl = %d, Alt = %d, AShift = 0x%x, ACtrl = 0x%x, AAlt = 0x%x, IsAd = %d, IsCon = %d, IsAlt = %d",
01145             KeySysMsg.Message,
01146             KeySysMsg.VirtKey,
01147             KeySysMsg.Extended,
01148             KeySysMsg.PrevDown,
01149             KeyPress::AdjustStateLeft | KeyPress::AdjustStateRight,
01150             KeyPress::ConstrainStateLeft | KeyPress::ConstrainStateRight,
01151             KeyPress::AlternativeStateLeft | KeyPress::AlternativeStateRight,
01152             AsyncShift,
01153             AsyncCtrl,
01154             AsyncAlt,
01155             (*ppKeyPress)->IsAdjust(),
01156             (*ppKeyPress)->IsConstrain(),
01157             (*ppKeyPress)->IsAlternative()
01158             );
01159             ENSURE(FALSE,s);
01160         }
01161   */
01162         //DumpKeyMessage(pMsg);
01163 
01164 #endif // _DEBUG
01165 
01166         // Return TRUE to say that it really was a keyboard message
01167         return TRUE;
01168     }
01169     else
01170         return FALSE;   // Not a keybaord type event that we're interested in
01171 }
01172 
01173 
01174 /********************************************************************************************
01175 
01176 >   static void KeyPress::ResetModifiers()
01177 
01178     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Equivalent to Tim's ResetModifierKeys() routine)
01179     Created:    26/08/94
01180     Purpose:    Maintain integrity of our key modifier status.  Win32S doesn't always
01181                 tell us what key events have occured - notably when the user uses Alt-TAB
01182                 to switch tasks.  Hence this gets called whenever our main window is
01183                 deactivated or activated.  The temporary tool is updated if required.
01184     SeeAlso:    UpdateTemporaryTool
01185 
01186 ********************************************************************************************/
01187 
01188 void KeyPress::ResetModifierKeys()
01189 {
01190     //ENSURE(FALSE,"KeyPress::ResetModifierKeys() called");
01191 
01192     // We can't trust Win32S to tell us about all keypreses we need to know about,
01193     // so set all modifiers to ff to avoid weird effects.
01194     if (INCOMPLETE_KEYS)
01195     {
01196         KeyPress::AdjustStateLeft       = FALSE;
01197         KeyPress::AdjustStateRight      = FALSE;
01198         KeyPress::ConstrainStateLeft    = FALSE;
01199         KeyPress::ConstrainStateRight   = FALSE;
01200         KeyPress::AlternativeStateLeft  = FALSE;
01201         KeyPress::AlternativeStateRight = FALSE;
01202         KeyPress::OptionStateLeft       = FALSE;
01203         KeyPress::OptionStateRight      = FALSE;
01204     }
01205 
01206     // Temporary tool may have changed - update it.
01207     //UpdateTemporaryTool();
01208 }
01209 
01210 
01211 
01212 /********************************************************************************************
01213 >   static BOOL KeyPress::IsAdjustPressed()
01214 
01215     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01216     Created:    1/12/94
01217     Inputs:     -
01218     Outputs:    -
01219     Returns:    TRUE if the "Adjust" key is currently depressed.
01220     Purpose:    Tests status of the "Adjust" key.
01221     Errors:     -
01222     SeeAlso:    -
01223 ********************************************************************************************/
01224 
01225 BOOL KeyPress::IsAdjustPressed()
01226 {
01227     return ::wxGetKeyState(CAMKEY(CC_MOD_ADJUST));
01228 }
01229 
01230 
01231 
01232 /********************************************************************************************
01233 >   static BOOL KeyPress::IsConstrainPressed()
01234 
01235     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01236     Created:    1/12/94
01237     Inputs:     -
01238     Outputs:    -
01239     Returns:    TRUE if the "Constrain" key is down.
01240     Purpose:    Tests status of the "Constrain" key.
01241     Errors:     -
01242     SeeAlso:    -
01243 ********************************************************************************************/
01244 
01245 BOOL KeyPress::IsConstrainPressed()
01246 {
01247     return ::wxGetKeyState(CAMKEY(CC_MOD_CONSTRAIN));
01248 }
01249 
01250 
01251 
01252 /********************************************************************************************
01253 >   static BOOL KeyPress::IsAlternativePressed()
01254 
01255     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01256     Created:    1/12/94
01257     Inputs:     -
01258     Outputs:    -
01259     Returns:    TRUE if the "Alternative" key is down.
01260     Purpose:    Tests status of the "Alternative" key.
01261     Errors:     -
01262     SeeAlso:    -
01263 ********************************************************************************************/
01264 
01265 BOOL KeyPress::IsAlternativePressed()
01266 {
01267     return ::wxGetKeyState(CAMKEY(CC_MOD_ALTERNATIVE));
01268 }
01269 
01270 /********************************************************************************************
01271 >   static BOOL KeyPress::IsKeyPressed(UINT32 VirtKey)
01272 
01273     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01274     Created:    26/7/94
01275     Inputs:     VirtKey = key to check
01276     Outputs:    -
01277     Returns:    TRUE if the VirtKey key is down.
01278     Purpose:    General async keypress func call.
01279     Errors:     -
01280     SeeAlso:    -
01281 ********************************************************************************************/
01282 
01283 BOOL KeyPress::IsKeyPressed(UINT32 VirtKey)
01284 {
01285     return ::wxGetKeyState( wxKeyCode(VirtKey) );
01286 }
01287 
01288 
01289 /********************************************************************************************
01290 
01291 >   static BOOL KeyPress::IsGalleryShiftPressed(void)
01292 
01293     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01294     Created:    9/2/95
01295 
01296     Returns:    TRUE if the "Gallery Shift" key is down.
01297 
01298     Purpose:    Tests status of the "Gallery Shift" key
01299                 This is a special method for use by galleries, which must emulate the
01300                 action of windows list boxes. "Gallery Shift" is the key used to select
01301                 multiple items at once.
01302 
01303     Notes:      SHOULD NOT be used outside the gallery system
01304 
01305 ********************************************************************************************/
01306 
01307 BOOL KeyPress::IsGalleryShiftPressed(void)
01308 {
01309     return ::wxGetKeyState(CAMKEY(SHIFT));
01310 }
01311 
01312 
01313 
01314 /********************************************************************************************
01315 
01316 >   static BOOL KeyPress::IsGalleryCtrlPressed(void)
01317 
01318     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01319     Created:    9/2/95
01320 
01321     Returns:    TRUE if the "Gallery Ctrl" key is down.
01322 
01323     Purpose:    Tests status of the "Gallery Ctrl" key
01324                 This is a special method for use by galleries, which must emulate the
01325                 action of windows list boxes. "Gallery Ctrl" is the key used to add/remove
01326                 single items to/from a selection
01327 
01328     Notes:      SHOULD NOT be used outside the gallery system
01329 
01330 ********************************************************************************************/
01331 
01332 BOOL KeyPress::IsGalleryCtrlPressed(void)
01333 {
01334     return ::wxGetKeyState(CAMKEY(CONTROL));
01335 }
01336 
01337 
01338        
01339 
01340 
01341 /********************************************************************************************
01342 
01343 >   static BOOL KeyPress::IsEscapePressed()
01344 
01345     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01346     Created:    16/9/94
01347     Inputs:     -
01348     Outputs:    -
01349     Returns:    TRUE  - if an escape key is being pressed, or was pressed since the last call
01350                         to this routine
01351                 FALSE - no escape key has been pressed
01352     Purpose:    Lets you see if an escape key combination is currently being pressed, or has been pressed
01353                 since the last call to this routine
01354 
01355                 It does a GetAsyncKeyState() on certain key combinations, currently -
01356                     CAMKEY(ESCAPE)
01357                     CAMKEY(CANCEL)  (Ctrl-Pause, or Break)
01358 
01359                 GetAsyncKeyState() returns the current key state AND whether the key was pressed since
01360                 the last call to GetAsyncKeyState().
01361 
01362                 Note:   If TRUE is returned, all pending key messages will have been removed before hand.
01363                         using PeekMessage(...WM_KEYFIRST,WM_KEYLAST,PM_REMOVE)
01364     SeeAlso:    
01365 
01366 ********************************************************************************************/
01367 
01368 BOOL KeyPress::IsEscapePressed()
01369 {
01370 PORTNOTE("other", "KeyPress::IsEscapePressed - do nothing" )
01371 #ifndef EXCLUDE_FROM_XARALX
01372 //  TRACE( _T("Warning - KeyPress::IsEscapePressed called") );
01373 /*  BOOL EscapePressed = (GetAsyncKeyState(CAMKEY(ESCAPE)) != 0);
01374     BOOL Pressed       = EscapePressed || (GetAsyncKeyState(CAMKEY(CANCEL)) != 0);
01375 
01376     if (Pressed)
01377     {
01378         BOOL EscapeKeyDown = FALSE;
01379 
01380         // Throw away all pending key messages
01381         MSG msg;
01382         while(PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ))
01383         {
01384             // If we the actual Escape key has been pressed, see if we got an Escape Key Down event.
01385             if (EscapePressed)
01386             {
01387                 KeyPressSysMsg KeyMsg(&msg);
01388                 if (KeyMsg.IsValid() && (KeyMsg.Message == KM_KEYDOWN) && (KeyMsg.VirtKey == CAMKEY(ESCAPE)))
01389                     EscapeKeyDown = TRUE;
01390             }
01391         }
01392 
01393         // Alt+Tab Esc fix - i.e. Aborting a task switch via Alt+Tab using the Escape key.
01394         //
01395         // If the actual Escape key has been pressed, only allow it if we have been posted a KeyDown event
01396         // for the Escape key.
01397         // 
01398         // When you do Alt+Tab while in Studio, then hit Escape, unfortunately we get posted an Escape Key Up event
01399         // which also means that the line above that reads "GetAsyncKeyState(CAMKEY(ESCAPE)) != 0" will return TRUE.
01400         // Obviously we want to ignore the Escape key being pressed in this circumstance, but it seems the only way 
01401         // to identify the Escape key press as one we don't want is to see if we *don't* have a corresponding
01402         // key down event.
01403         //
01404         // if (GetAsyncKeyState(CAMKEY(ESCAPE)) != 0)  // i.e. the Escape key has been pressed
01405         // {
01406         //     if (App received a Escape KeyDown message)
01407         //        Legitimate Escape key press, so Pressed = TRUE
01408         //     else
01409         //        Escape hit outside our app, so ignore it
01410         // }
01411 
01412         // If the ActualEscape key has been pressed, then Pressed should only be TRUE if we have received a
01413         // Escape Key Down event.
01414         if (EscapePressed)
01415             Pressed = EscapeKeyDown;
01416     }
01417 
01418     return (Pressed); */
01419 #endif
01420     return false;
01421 }
01422 
01423 /********************************************************************************************
01424 
01425 >   static BOOL KeyPress::EscapePressed(KeyPress* pKeyPress)
01426 
01427     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01428     Created:    15/9/94
01429     Inputs:     pKeyPress = ptr to a key press
01430     Outputs:    -
01431     Returns:    TRUE  - the key was an escape event (e.g. Escape, Break, etc)
01432                 FALSE - the key was not an escape key, nothing happened
01433     Purpose:    Deals with an Escape key press
01434 
01435                 If the key press was NOT an escape key, (i.e. not Escape or Ctrl+Pause (Break)),
01436                 nothing happens, and FALSE is returned
01437 
01438                 if it was an escape key press, it is processed in a relevent way
01439                 At the moment, this just means that the current drag is terminated, if there is one.
01440 
01441                 If it's an escape key press, and it was acted upon (e.g. a drag was terminated), TRUE is returned.
01442                 Otherwise FALSE is returned
01443     SeeAlso:    
01444 
01445 ********************************************************************************************/
01446 
01447 BOOL KeyPress::EscapePressed(KeyPress* pKeyPress)
01448 {
01449     ENSURE(pKeyPress->IsValid(),"Invalid KeyPress given");
01450 
01451     BOOL Processed = FALSE;
01452     UINT32 VirtKey = pKeyPress->GetVirtKey();
01453 
01454     // Only check non-auto-repeat "key down" key presses
01455     if (pKeyPress->IsPress() && !pKeyPress->IsRepeat())
01456     {
01457         if (VirtKey == CAMKEY(ESCAPE) || VirtKey == WXK_CANCEL)
01458         {
01459 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)                       
01460             // MarkN I've moved this code in an attempt to stop the selection being
01461             // cleared after a bar drag cancel - Chris.
01462             if (!Processed)
01463                 Processed = BaseBar::EscPressed(TRUE);
01464 
01465             // cancel any drag manager drags (and say that we have done so!!!)
01466             // stops the selection being cleared when you cancel a
01467             // colour or sprite (or any) DragManagerOp drag
01468             if(!Processed && DragManagerOp::GetCurrentManager() != NULL)
01469             {
01470                 DragManagerOp::AbortDrag();
01471                 Processed = TRUE;
01472             }
01473 #endif
01474 
01475             if (!Processed && Operation::GetCurrentDragOp() != NULL)
01476             {
01477                 OilCoord PointerPos(0,0);
01478                 ClickModifiers ClickMods;
01479 //              Spread* pSpread = NULL;
01480 
01481                 DocView* pDocView = DocView::GetSelected();
01482                 if (pDocView)
01483                     pDocView->DragFinished(Operation::GetCurrentDragOp(), PointerPos, ClickMods, FALSE);
01484 
01485                 // We've done something with this escape key press so set Processed to TRUE
01486                 // to prevent it from being passed on
01487                 Processed = (Operation::GetCurrentDragOp() == NULL);
01488             }
01489 
01490             if (!Processed && Operation::GetCurrentDragOp() != NULL)
01491             {
01492                 DocCoord PointerPos(0,0);
01493                 ClickModifiers ClickMods;
01494                 Spread* pSpread = NULL;
01495 
01496                 Operation::GetCurrentDragOp()->DragFinished(PointerPos, ClickMods, pSpread, FALSE, FALSE);
01497 
01498                 // We've done something with this escape key press so set Processed to TRUE
01499                 // to prevent it from being passed on
01500                 Processed = TRUE;
01501             }
01502 
01503             // This gives Chris a chance to terminate his bar dragging.  This was necessary as his former
01504             // way of detecting Escape (via KeyMsg broadcasts) no longer works because Escape is now a hot key, and
01505             // as such gets in there before a KeyMsg is broadcast.
01506             // (MarkN 27/4/95)
01507             /*if (!Processed)
01508                 Processed = BaseBar::EscPressed(TRUE);
01509               */
01510             // Throw away all pending key messages
01511 PORTNOTE( "other", "Remove PeekMessage" )
01512 #if !defined(EXCLUDE_FROM_XARALX)                       
01513             MSG msg;
01514             while(PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ))
01515             ;
01516 #endif
01517         }
01518     }
01519 
01520     return Processed;
01521 }
01522 
01523 /********************************************************************************************
01524 
01525 >   static BOOL KeyPress::GenerateCharMessage(MSG* pMsg)
01526 
01527     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 
01528     Created:    10/3/95
01529     Inputs:     pMsg = A Windows keypress message
01530     Outputs:    -
01531     Returns:    TRUE  if the message was processed
01532                 FALSE if the message wasn't processed
01533     Purpose:    This tries to see if the keypress message can generate a WM_CHAR message.
01534 
01535                 It does this by trapping numerical key pad entry of the ASCII value of the char while
01536                 the Alt ky is held down. (e.g. hold down ALT, type '6' then '5' on the num key pad, then release
01537                 Alt - you should get 'A' appearing at the input focus).  If, on a Alt key up event we have a
01538                 valid ASCII value that's been entered, we post ourselves a WM_CHAR message containing the ASCII
01539                 char.
01540 
01541                 We have to do this ourselves because we get less messages generated in Win 3.1 than we do in
01542                 NT, so the NT solution (act upon the auto generated WM_CHAR message) won't work an all target
01543                 platforms (pain in the butt or what?). The ideal solution is to find out exactly why we don't
01544                 get this extra WM_CHAR message in Win3.1, but I've traced paths of key press messages under NT
01545                 and have found no obvious reason why the Win3.1 should behave differently. As we don't have single
01546                 stepping technology under Win3.1, it's almost impossible to determine what's going on.
01547 
01548                 So, the time honoured CC tradition, if the OS doesn't do it, we'll do it ourselves.
01549 
01550 
01551     Errors:     -
01552     SeeAlso:    KeyPress::TranslateMessage
01553 
01554 ********************************************************************************************/
01555 
01556 BOOL KeyPress::GenerateCharMessage(wxKeyEvent* pMsg)
01557 {
01558     BOOL Processed = FALSE;
01559 
01560     // Get the virtual key code for the key pressed
01561     UINT32 VirtKey = pMsg->GetKeyCode();
01562 
01563     //DumpKeyMessage(pMsg);
01564 
01565     if( wxEVT_KEY_DOWN == pMsg->GetEventType() ) 
01566     {
01567         if (VirtKey == CAMKEY(MENU))
01568         {
01569             // Trap ALL Alt key down messages
01570 
01571             if (!KeyPress::ValidAsciiVal)
01572             {
01573                 // Initialise a ASCII value entry
01574                 //TRACE( _T("-*-*-*-- Starting valid ascii val\n"));
01575                 KeyPress::ValidAsciiVal = TRUE;
01576                 KeyPress::AsciiVal      = -1;
01577             }
01578         }
01579         else if (KeyPress::ValidAsciiVal && ((VirtKey < CAMKEY(NUMPAD0)) || (VirtKey > WXK_NUMPAD9)))
01580         {
01581             // If the key down message is not a num pad key between '0' and '9'
01582             // invalidate the ASCII value
01583             //TRACE( _T("-*-*-*-- (keydown) Invalidating ascii val\n"));
01584             KeyPress::ValidAsciiVal = FALSE;
01585         }
01586     }
01587     else
01588     if( wxEVT_KEY_UP == pMsg->GetEventType() ) 
01589     {
01590         if (KeyPress::ValidAsciiVal)
01591         {
01592             // Only try to produce an ASCII value if the last set of key presses has generated
01593             // a valid value
01594 
01595             if (VirtKey == CAMKEY(MENU))
01596             {
01597                 // We've received a Alt key up message, so post ourselves a WM_CHAR message that
01598                 // contains the generated ASCII value
01599 
01600                 if (KeyPress::AsciiVal >= 0)
01601                 {
01602                     // Only post the ASCII value if one's been specified via the Num key pad
01603                     // (i.e. the value >= 0)
01604                     //TRACE( _T("-*-*-*-- Posting WM_CHAR. Val = %ld\n"),KeyPress::AsciiVal);
01605 PORTNOTE("other", "Removed PostMessage usage - WM_CHAR from ascii code" )
01606 #ifndef EXCLUDE_FROM_XARALX
01607                     Processed = ::PostMessage(pMsg->hwnd,WM_CHAR,KeyPress::AsciiVal % 256,1);
01608 #endif
01609                 }
01610                 //TRACE( _T("-*-*-*-- (keyup) Invalidating ascii val. Val = %ld\n"),KeyPress::AsciiVal);
01611                 KeyPress::ValidAsciiVal = FALSE;
01612             }
01613             else if ((VirtKey >= CAMKEY(NUMPAD0)) && (VirtKey <= WXK_NUMPAD9))
01614             {
01615                 // We've got a num key pad key up event
01616                 // We have to do this bit on key up events, because for some reason under NT (and possibly
01617                 // other OSs) we don't get a key down event for the first key that's pressed while the
01618                 // Alt key is auto-repeating (wierd - any ideas welcome)
01619 
01620                 // If this is the first one (i.e. ASCII val is currently < 0), reset the value to 0
01621                 if (KeyPress::AsciiVal < 0)
01622                     KeyPress::AsciiVal = 0;
01623 
01624                 // Shift the current value up, and add in the digit of the num key pad key.
01625                 KeyPress::AsciiVal = ((KeyPress::AsciiVal*10)+(VirtKey-CAMKEY(NUMPAD0)));
01626 
01627                 // We've processed this key press
01628                 Processed = TRUE;
01629 
01630                 //TRACE( _T("-*-*-*-- ascii val digit received. Val = %ld\n"),KeyPress::AsciiVal);
01631             }
01632         }
01633     }
01634 
01635     return Processed;
01636 }
01637 
01638 /********************************************************************************************
01639 
01640 >   static BOOL KeyPress::TranslateMessage(MSG* pMsg)
01641 
01642     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 
01643     Created:    26/08/94
01644     Inputs:     pMsg = A Windows message
01645     Outputs:    -
01646     Returns:    TRUE  if the message was to do with a key press AND was processed
01647                 FALSE if the message wasn't to do with the keyboard at all OR key press was not processed
01648     Purpose:    Called from a low-level PreTranslateMessage() routine to allow key presses to be processed
01649                 If it is a key press message, it generates a KeyPress object and sends it off to
01650                 Application::OnKeyPress()
01651     Errors:     -
01652     SeeAlso:    Application::OnKeyPress
01653 
01654 ********************************************************************************************/
01655 
01656 BOOL KeyPress::TranslateMessage(wxKeyEvent* pMsg)
01657 {
01658 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01659     // What kind of message is it?
01660     BOOL KeyDown = wxEVT_KEY_DOWN == pMsg->GetEventType();
01661     BOOL KeyUp   = wxEVT_KEY_UP == pMsg->GetEventType();
01662 
01663     // If it's a key event, lose the bubble help.
01664     if (KeyDown || KeyUp)
01665         ControlHelper::BubbleHelpDisable();
01666 #endif
01667     
01668     TRACEUSER( "jlh92", _T("TM - %s\n"), wxEVT_KEY_DOWN == pMsg->GetEventType() ? _T("KDN") :
01669         wxEVT_KEY_UP == pMsg->GetEventType() ? _T("KUP") : wxEVT_CHAR == pMsg->GetEventType() ? _T("KCH") : 
01670         _T("K??") );
01671 
01672     // Normal key processing.
01673     KeyPress* pKeyPress;
01674     BOOL Processed = FALSE;
01675 
01676     // See if we can generate an WM_CHAR message from the key press
01677     if (!Processed)
01678         Processed = GenerateCharMessage(pMsg);
01679 
01680     // Can we make a key press event from this message?
01681     if (!Processed && KeyPress::GenerateKeyPress(pMsg,&pKeyPress))
01682     {
01683         if (pKeyPress != NULL)
01684         {
01685             // The message was a key press and we have a key press object at pKeyPress
01686 
01687             // check for an escape key press
01688             if (!Processed)
01689                 Processed = EscapePressed(pKeyPress);
01690 
01691             // Now see if Camelot wants to use it
01692             if (!Processed)
01693                 Processed = GetApplication()->OnKeyPress(pKeyPress);
01694 
01695             // Don't process Alt key presses.  By always returning FALSE on Alt key presses, we get
01696             // normal functionality from single press/releases of Alt, even in the Selector tool
01697             if (Processed && pKeyPress->VirtKey == CAMKEY(MENU))
01698                 Processed = FALSE;
01699 
01700             //TRACE( _T("Processed = %d\n"),Processed);
01701 
01702             // Must delete the key press after use
01703             delete pKeyPress;
01704         }
01705     }
01706 
01707     if (!Processed)
01708     {
01709         // MFC ISSUES...
01710         // If we have had a key press we wish to ignore totally (i.e. repeated modifier key presses)
01711         // then return TRUE so that it doesn't get passed onto the rest of MFC.
01712         //
01713         // This is mainly for performance improvements during a drag AND modifier key press op, e.g. Alt held down
01714         // in the freehand tool for drawing straight lines.
01715         //
01716         // This fix makes modified drags usable in retail builds.  In debug builds, you get an extra hit with
01717         // AfxValidateObject (or what ever it's called), which takes about 50% of the time.
01718         //
01719         // During Drags:
01720         // We want to prevent key presses getting to MFC during drags.  In particular things like 
01721         // Ctrl-Tab (i.e. switch to new doc)
01722 
01723         KeyPressSysMsg KeySysMsg(pMsg);
01724         if (KeySysMsg.IsValid())
01725         {
01726             // We have a keypress message
01727             // Prevent it getting to MFC if we are dragging or it's one we wish to ignore
01728             Processed = ((Operation::GetCurrentDragOp()!=NULL) || IgnoreKeyMessage(&KeySysMsg));
01729         }
01730     }
01731 
01732     return Processed;
01733 }
01734  
01735 /********************************************************************************************
01736 
01737 >   INT32 KeyPress::operator==(const KeyPress& other)
01738 
01739     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01740     Created:    26/8/94
01741     Inputs:     other = the key press you wish to check for equivalence with this key press
01742     Outputs:    -
01743     Returns:    TRUE if equal, FALSE otherwise
01744     Purpose:    KeyPress == operator
01745                 Two KeyPress objects are equal if
01746                     1) They have the same virtual key code
01747                     2) Have the same modifier settings
01748                     3) Have the same extended flag settings
01749                     4) Have the same validity (i.e. both valid OR both invalid)
01750 
01751                 THIS DOES NOT COMPARE THE UNICODE COMPONENTS OF THE TWO KeyPress OBJECTS.
01752                 To compare Unicode values, use the KeyPress::GetUnicode() func.
01753     Errors:     -
01754     SeeAlso:    KeyPress::GetUnicode()
01755 
01756 ********************************************************************************************/
01757 
01758 INT32 KeyPress::operator==(const KeyPress& other)
01759 {
01760     return ( 
01761             VirtKey     == other.VirtKey     &&
01762             Adjust      == other.Adjust      &&
01763             Constrain   == other.Constrain   &&
01764             Alternative == other.Alternative &&
01765             Option      == other.Option      && 
01766             Extended    == other.Extended    &&
01767             Valid       == other.Valid
01768            );
01769 }
01770 
01771 
01772 
01773 /********************************************************************************************
01774 
01775 >   static BOOL KeyPress::AddVirtualKeyCode(UINT32 VCode, WCHAR Unicode)
01776 
01777     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01778     Created:    11/10/95
01779     Inputs:     VCode - the virtual key code to add
01780                 Unicode - the unicode value generated when this key is pressed
01781     Outputs:    -
01782     Returns:    TRUE/FALSE for success/failure
01783     Purpose:    Adds the given virtual key code to the list that Camelot knows about and
01784                 send around internally (rather than ignoring)
01785     Errors:     -
01786     SeeAlso:    -
01787 
01788 ********************************************************************************************/
01789 BOOL KeyPress::AddVirtualKeyCode(UINT32 VCode, WCHAR Unicode)
01790 {
01791     // Construct a list item
01792     AdditionalVirtKey* pNew = new AdditionalVirtKey;
01793 
01794     if (pNew != NULL)
01795     {
01796         pNew->VirtualKeyCode = VCode;
01797         pNew->UnicodeValue = Unicode;
01798 
01799         AdditionalVirtKeys.AddHead(pNew);
01800     }
01801 
01802     return (pNew != NULL);
01803 }
01804 
01805 
01806 
01807 /********************************************************************************************
01808 
01809 >   void KeyPress::RemoveVirtualKeyCode(UINT32 VCode, WCHAR Unicode)
01810 
01811     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01812     Created:    11/10/95
01813     Inputs:     VCode - the virtual key code to remove
01814                 Unicode - the unicode value generated when this key is pressed
01815     Outputs:    -
01816     Returns:    -
01817     Purpose:    Removes the given virtual key code that generates the givne unicode value
01818                 from the list of additional virtual key codes.  Only the first occurace is
01819                 removed.
01820     Errors:     -
01821     SeeAlso:    -
01822 
01823 ********************************************************************************************/
01824 void KeyPress::RemoveVirtualKeyCode(UINT32 VCode, WCHAR Unicode)
01825 {
01826     // Loop through the list until we find the list item
01827     BOOL finished = FALSE;
01828     AdditionalVirtKey* pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetHead();
01829 
01830     while (!finished && (pKey != NULL))
01831     {
01832         AdditionalVirtKey* pNext = (AdditionalVirtKey*)AdditionalVirtKeys.GetNext(pKey);
01833         
01834         if ((pKey->VirtualKeyCode == VCode) && (pKey->UnicodeValue == Unicode))
01835         {
01836             AdditionalVirtKeys.RemoveItem(pKey);
01837             delete pKey;
01838             finished = TRUE;
01839         }
01840 
01841         pKey = pNext;
01842     }
01843 }
01844 
01845 
01846 
01847 //----------------------------------------------------------------------------------------------------
01848 
01849 #if defined(_DEBUG) && defined(__WXMSW__)
01850 
01851 void KeyPress::DumpKeyMessage(wxKeyEvent* pMsg)
01852 {
01853     PORTNOTETRACE("other", "KeyPress::DumpKeyMessage - do nothing" );
01854 #ifndef EXCLDUE_FROM_XARALX
01855     //if (!IsUserName("Markn")) return;
01856 
01857     KeyPressSysMsg KeySysMsg(pMsg);
01858     WCHAR c = 1;
01859     KeyPress k1(&KeySysMsg,c);
01860     KeyPress k2(&KeySysMsg,c);
01861 
01862     BOOL tits = (k1 == k2);
01863 
01864     BOOL KeyMsg = ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST));
01865 
01866     if (KeyMsg)
01867     {
01868         if (pMsg->message == WM_KEYDOWN)        TRACE( _T("*** WM_KEYDOWN"));
01869         if (pMsg->message == WM_KEYUP)          TRACE( _T("*** WM_KEYUP"));
01870         if (pMsg->message == WM_SYSKEYDOWN)     TRACE( _T("*** WM_SYSKEYDOWN"));
01871         if (pMsg->message == WM_SYSKEYUP)       TRACE( _T("*** WM_SYSKEYUP"));
01872         if (pMsg->message == WM_CHAR)           TRACE( _T("*** WM_CHAR"));
01873         if (pMsg->message == WM_DEADCHAR)       TRACE( _T("*** WM_DEADCHAR"));
01874         if (pMsg->message == WM_SYSCHAR)        TRACE( _T("*** WM_SYSCHAR"));
01875         if (pMsg->message == WM_SYSDEADCHAR)    TRACE( _T("*** WM_SYSDEADCHAR"));
01876 
01877         UINT32 VirtKey  = pMsg->wParam;
01878         INT32 KeyData  = pMsg->lParam;
01879 
01880         if (TRUE)
01881         {
01882             TRACE( _T(" VK=%lx\n"),VirtKey);
01883         }
01884         else
01885         {
01886             TRACE( _T("\n"));
01887             TRACE( _T("KeyData = %lx\n"),KeyData);
01888             TRACE( _T("VirtKey = %lx\n"),VirtKey);
01889             TRACE( _T("Repeat  = %lx\n"),KeyData & 0xffff);
01890             TRACE( _T("ScanCode= %lx\n\n"),(KeyData >> 16) & 0xff);
01891 
01892             TRACE( _T("Bit 24 (extended)   = %lx\n"),KeyData & 1<<24);
01893             TRACE( _T("Bit 29 (context)    = %lx\n"),KeyData & 1<<29);
01894             TRACE( _T("Bit 30 (prev state) = %lx\n"),KeyData & 1<<30);
01895             TRACE( _T("Bit 31 (trans stat) = %lx\n"),KeyData & 1<<31);
01896 
01897             //TRACE( _T("\nBit 25 (reserved)   = %lx\n"),KeyData & 1<<25);
01898             //TRACE( _T("Bit 26 (reserved)   = %lx\n"),KeyData & 1<<26);
01899             //TRACE( _T("Bit 27 (reserved)   = %lx\n"),KeyData & 1<<27);
01900             //TRACE( _T("Bit 28 (reserved)   = %lx\n"),KeyData & 1<<28);
01901 
01902             TRACE( _T("KeyPress::AdjustStateLeft       = %lx\n"),KeyPress::AdjustStateLeft);
01903             TRACE( _T("KeyPress::AdjustStateRight      = %lx\n"),KeyPress::AdjustStateRight);
01904             TRACE( _T("KeyPress::ConstrainStateLeft    = %lx\n"),KeyPress::ConstrainStateLeft);
01905             TRACE( _T("KeyPress::ConstrainStateRight   = %lx\n"),KeyPress::ConstrainStateRight);
01906             TRACE( _T("KeyPress::AlternativeStateLeft  = %lx\n"),KeyPress::AlternativeStateLeft);
01907             TRACE( _T("KeyPress::AlternativeStateRight = %lx\n"),KeyPress::AlternativeStateRight);
01908         }
01909     }
01910 #endif
01911 }
01912 #endif  // _DEBUG
01913 
01914 
01915 

Generated on Sat Nov 10 03:48:38 2007 for Camelot by  doxygen 1.4.4