optionally use guarded alloc for tiles compositor, also replace allocation functions...
[blender.git] / source / gameengine / GameLogic / SCA_KeyboardSensor.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * Sensor for keyboard input
27  */
28
29 /** \file gameengine/GameLogic/SCA_KeyboardSensor.cpp
30  *  \ingroup gamelogic
31  */
32
33
34 #include <stddef.h>
35
36 #include "SCA_KeyboardSensor.h"
37 #include "SCA_KeyboardManager.h"
38 #include "SCA_LogicManager.h"
39 #include "StringValue.h"
40 #include "SCA_IInputDevice.h"
41
42 extern "C" {
43         #include "BLI_string_cursor_utf8.h"
44 }
45
46 /* ------------------------------------------------------------------------- */
47 /* Native functions                                                          */
48 /* ------------------------------------------------------------------------- */
49
50 SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
51                                                                            short int hotkey,
52                                                                            short int qual,
53                                                                            short int qual2,
54                                                                            bool bAllKeys,
55                                                                            const STR_String& targetProp,
56                                                                            const STR_String& toggleProp,
57                                                                            SCA_IObject* gameobj,
58                                                                            short int exitKey)
59         :SCA_ISensor(gameobj,keybdmgr),
60          m_hotkey(hotkey),
61          m_qual(qual),
62          m_qual2(qual2),
63          m_bAllKeys(bAllKeys),
64          m_targetprop(targetProp),
65          m_toggleprop(toggleProp)
66 {
67         if (hotkey == exitKey)
68                 keybdmgr->GetInputDevice()->HookEscape();
69 //      SetDrawColor(0xff0000ff);
70         Init();
71 }
72
73
74
75 SCA_KeyboardSensor::~SCA_KeyboardSensor()
76 {
77 }
78
79 void SCA_KeyboardSensor::Init()
80 {
81         // this function is used when the sensor is disconnected from all controllers
82         // by the state engine. It reinitializes the sensor as if it was just created.
83         // However, if the target key is pressed when the sensor is reactivated, it
84         // will not generated an event (see remark in Evaluate()).
85         m_val = (m_invert)?1:0;
86         m_reset = true;
87 }
88
89 CValue* SCA_KeyboardSensor::GetReplica()
90 {
91         SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this);
92         // this will copy properties and so on...
93         replica->ProcessReplica();
94         replica->Init();
95         return replica;
96 }
97
98
99
100 short int SCA_KeyboardSensor::GetHotkey()
101 {
102         return m_hotkey;
103 }
104
105
106
107 bool SCA_KeyboardSensor::IsPositiveTrigger()
108
109         bool result = (m_val != 0);
110
111         if (m_invert)
112                 result = !result;
113                 
114         return result;
115 }
116
117
118
119 bool SCA_KeyboardSensor::TriggerOnAllKeys()
120
121         return m_bAllKeys;
122 }
123
124
125
126 bool SCA_KeyboardSensor::Evaluate()
127 {
128         bool result    = false;
129         bool reset     = m_reset && m_level;
130         bool qual          = true;
131         bool qual_change = false;
132         short int m_val_orig = m_val;
133         
134         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
135         //      cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n";
136
137         /* See if we need to do logging: togPropState exists and is
138          * different from 0 */
139         CValue* myparent = GetParent();
140         CValue* togPropState = myparent->GetProperty(m_toggleprop);
141         if (togPropState &&
142                 (((int)togPropState->GetNumber()) != 0) )
143         {
144                 LogKeystrokes();
145         }
146
147         m_reset = false;
148
149         /* Now see whether events must be bounced. */
150         if (m_bAllKeys)
151         {
152                 bool justactivated = false;
153                 bool justreleased = false;
154                 bool active = false;
155
156                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
157                 {
158                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
159                         switch (inevent.m_status) 
160                         { 
161                         case SCA_InputEvent::KX_JUSTACTIVATED:
162                                 justactivated = true;
163                                 break;
164                         case SCA_InputEvent::KX_JUSTRELEASED:
165                                 justreleased = true;
166                                 break;
167                         case SCA_InputEvent::KX_ACTIVE:
168                                 active = true;
169                                 break;
170                         case SCA_InputEvent::KX_NO_INPUTSTATUS:
171                                 /* do nothing */
172                                 break;
173                         }
174                 }
175
176                 if (justactivated)
177                 {
178                         m_val=1;
179                         result = true;
180                 } else
181                 {
182                         if (justreleased)
183                         {
184                                 m_val=(active)?1:0;
185                                 result = true;
186                         } else
187                         {
188                                 if (active)
189                                 {
190                                         if (m_val == 0)
191                                         {
192                                                 m_val = 1;
193                                                 if (m_level) {
194                                                         result = true;
195                                                 }
196                                         }
197                                 } else
198                                 {
199                                         if (m_val == 1)
200                                         {
201                                                 m_val = 0;
202                                                 result = true;
203                                         }
204                                 }
205                         }
206                         if (m_tap)
207                                 // special case for tap mode: only generate event for new activation
208                                 result = false;
209                 }
210
211
212         } else
213         {
214
215         //              cerr << "======= SCA_KeyboardSensor::Evaluate:: peeking at key status" << endl;
216                 const SCA_InputEvent & inevent = inputdev->GetEventValue(
217                         (SCA_IInputDevice::KX_EnumInputs) m_hotkey);
218         
219         //              cerr << "======= SCA_KeyboardSensor::Evaluate:: status: " << inevent.m_status << endl;
220                 
221                 
222                 /* Check qualifier keys
223                  * - see if the qualifiers we request are pressed - 'qual' true/false
224                  * - see if the qualifiers we request changed their state - 'qual_change' true/false
225                  */
226                 if (m_qual > 0) {
227                         const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual);
228                         switch(qualevent.m_status) {
229                         case SCA_InputEvent::KX_NO_INPUTSTATUS:
230                                 qual = false;
231                                 break;
232                         case SCA_InputEvent::KX_JUSTRELEASED:
233                                 qual_change = true;
234                                 qual = false;
235                                 break;
236                         case SCA_InputEvent::KX_JUSTACTIVATED:
237                                 qual_change = true;
238                         case SCA_InputEvent::KX_ACTIVE:
239                                 /* do nothing */
240                                 break;
241                         }
242                 }
243                 if (m_qual2 > 0 && qual==true) {
244                         const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual2);
245                         /* copy of above */
246                         switch(qualevent.m_status) {
247                         case SCA_InputEvent::KX_NO_INPUTSTATUS:
248                                 qual = false;
249                                 break;
250                         case SCA_InputEvent::KX_JUSTRELEASED:
251                                 qual_change = true;
252                                 qual = false;
253                                 break;
254                         case SCA_InputEvent::KX_JUSTACTIVATED:
255                                 qual_change = true;
256                         case SCA_InputEvent::KX_ACTIVE:
257                                 /* do nothing */
258                                 break;
259                         }
260                 }
261                 /* done reading qualifiers */
262                 
263                 if (inevent.m_status == SCA_InputEvent::KX_NO_INPUTSTATUS)
264                 {
265                         if (m_val == 1)
266                         {
267                                 // this situation may occur after a scene suspend: the keyboard release 
268                                 // event was not captured, produce now the event off
269                                 m_val = 0;
270                                 result = true;
271                         }
272                 } else
273                 {
274                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
275                         {
276                                 m_val=1;
277                                 result = true;
278                         } else
279                         {
280                                 if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
281                                 {
282                                         m_val = 0;
283                                         result = true;
284                                 } else 
285                                 {
286                                         if (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
287                                         {
288                                                 if (m_val == 0)
289                                                 {
290                                                         m_val = 1;
291                                                         if (m_level) 
292                                                         {
293                                                                 result = true;
294                                                         }
295                                                 }
296                                         }
297                                 }
298                         }
299                 }
300                 
301                 /* Modify the key state based on qual(s)
302                  * Tested carefully. don't touch unless your really sure.
303                  * note, this will only change the results if key modifiers are set.
304                  *
305                  * When all modifiers and keys are positive
306                  *  - pulse true
307                  * 
308                  * When ANY of the modifiers or main key become inactive,
309                  *  - pulse false
310                  */
311                 if (qual==false) { /* one of the qualifiers are not pressed */
312                         if (m_val_orig && qual_change) { /* we were originally enabled, but a qualifier changed */
313                                 result = true;
314                         } else {
315                                 result = false;
316                         }
317                         m_val = 0; /* since one of the qualifiers is not on, set the state to false */
318                 } else {                                                /* we done have any qualifiers or they are all pressed */
319                         if (m_val && qual_change) {     /* the main key state is true and our qualifier just changed */
320                                 result = true;
321                         }
322                 }
323                 /* done with key quals */
324                 
325         }
326         
327         if (reset)
328                 // force an event
329                 result = true;
330         return result;
331
332 }
333
334 void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
335 {
336         if (IsPrintable(keyIndex)) {
337                 CValue* tprop = GetParent()->GetProperty(m_targetprop);
338                 
339                 if (tprop) {
340                         /* overwrite the old property */
341                         if (IsDelete(keyIndex)) {
342                                 /* strip one char, if possible */
343                                 STR_String newprop = tprop->GetText();
344                                 int oldlength = newprop.Length();
345                                 if (oldlength >= 1 ) {
346                                         int newlength=oldlength;
347
348                                         BLI_str_cursor_step_prev_utf8(newprop, newprop.Length(), &newlength);
349                                         newprop.SetLength(newlength);
350
351                                         CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
352                                         GetParent()->SetProperty(m_targetprop, newstringprop);
353                                         newstringprop->Release();
354                                 }                               
355                         } else {
356                                 /* append */
357                                 char pchar = ToCharacter(keyIndex, IsShifted());
358                                 STR_String newprop = tprop->GetText() + pchar;
359                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
360                                 GetParent()->SetProperty(m_targetprop, newstringprop);
361                                 newstringprop->Release();
362                         }
363                 } else {
364                         if (!IsDelete(keyIndex)) {
365                                 /* Make a new property. Deletes can be ignored. */
366                                 char pchar = ToCharacter(keyIndex, IsShifted());
367                                 STR_String newprop = pchar;
368                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
369                                 GetParent()->SetProperty(m_targetprop, newstringprop);
370                                 newstringprop->Release();
371                         }
372                 }
373         }
374         
375 }
376         
377 /**
378  * Tests whether shift is pressed
379  */     
380 bool SCA_KeyboardSensor::IsShifted(void)
381 {
382         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
383         
384         if ( (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
385                   == SCA_InputEvent::KX_ACTIVE)
386                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
387                          == SCA_InputEvent::KX_JUSTACTIVATED)
388                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
389                          == SCA_InputEvent::KX_ACTIVE)
390                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
391                          == SCA_InputEvent::KX_JUSTACTIVATED)
392                 ) {
393                 return true;
394         } else {
395                 return false;
396         }       
397 }
398
399 void SCA_KeyboardSensor::LogKeystrokes(void) 
400 {
401         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
402         int num = inputdev->GetNumActiveEvents();
403
404         /* weird loop, this one... */
405         if (num > 0)
406         {
407                 
408                 int index = 0;
409                 /* Check on all keys whether they were pushed. This does not
410                  * untangle the ordering, so don't type too fast :) */
411                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
412                 {
413                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
414                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
415                         {
416                                 if (index < num)
417                                 {
418                                         AddToTargetProp(i);
419                                         index++;
420                                 }
421                         }
422                 }
423         }
424 }
425
426 #ifdef WITH_PYTHON
427
428 /* ------------------------------------------------------------------------- */
429 /* Python Functions                                                    */
430 /* ------------------------------------------------------------------------- */
431
432 KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
433 "getKeyStatus(keycode)\n"
434 "\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
435 {
436         if (!PyLong_Check(value)) {
437                 PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int");
438                 return NULL;
439         }
440         
441         int keycode = PyLong_AsSsize_t(value);
442         
443         if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
444                 || (keycode > SCA_IInputDevice::KX_ENDKEY)) {
445                 PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!");
446                 return NULL;
447         }
448         
449         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
450         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
451         return PyLong_FromSsize_t(inevent.m_status);
452 }
453
454 /* ------------------------------------------------------------------------- */
455 /* Python Integration Hooks                                            */
456 /* ------------------------------------------------------------------------- */
457
458 PyTypeObject SCA_KeyboardSensor::Type = {
459         PyVarObject_HEAD_INIT(NULL, 0)
460         "SCA_KeyboardSensor",
461         sizeof(PyObjectPlus_Proxy),
462         0,
463         py_base_dealloc,
464         0,
465         0,
466         0,
467         0,
468         py_base_repr,
469         0,0,0,0,0,0,0,0,0,
470         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
471         0,0,0,0,0,0,0,
472         Methods,
473         0,
474         0,
475         &SCA_ISensor::Type,
476         0,0,0,0,0,0,
477         py_base_new
478 };
479
480 PyMethodDef SCA_KeyboardSensor::Methods[] = {
481         KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus),
482         {NULL,NULL} //Sentinel
483 };
484
485 PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
486         KX_PYATTRIBUTE_RO_FUNCTION("events", SCA_KeyboardSensor, pyattr_get_events),
487         KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys),
488         KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey),
489         KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual),
490         KX_PYATTRIBUTE_SHORT_RW("hold2",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual2),
491         KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,MAX_PROP_NAME,false,SCA_KeyboardSensor,m_toggleprop),
492         KX_PYATTRIBUTE_STRING_RW("targetProperty",0,MAX_PROP_NAME,false,SCA_KeyboardSensor,m_targetprop),
493         { NULL }        //Sentinel
494 };
495
496
497 PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
498 {
499         SCA_KeyboardSensor* self= static_cast<SCA_KeyboardSensor*>(self_v);
500         
501         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)self->m_eventmgr)->GetInputDevice();
502
503         PyObject* resultlist = PyList_New(0);
504         
505         for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
506         {
507                 const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
508                 if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
509                 {
510                         PyObject* keypair = PyList_New(2);
511                         PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
512                         PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
513                         PyList_Append(resultlist,keypair);
514                 }
515         }       
516         return resultlist;
517 }
518
519 #endif // WITH_PYTHON
520
521 /* Accessed from python */
522
523 // this code looks ugly, please use an ordinary hashtable
524
525 char ToCharacter(int keyIndex, bool shifted)
526 {
527         /* numerals */
528         if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
529                  && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
530                 if (shifted) {
531                         char numshift[] = ")!@#$%^&*(";
532                         return numshift[keyIndex - '0']; 
533                 } else {
534                         return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
535                 }
536         }
537         
538         /* letters... always lowercase... is that desirable? */
539         if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
540                  && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
541                 if (shifted) {
542                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
543                 } else {
544                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
545                 }
546         }
547         
548         if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
549                 return ' ';
550         }
551         if (keyIndex == SCA_IInputDevice::KX_RETKEY || keyIndex == SCA_IInputDevice::KX_PADENTER) {
552                 return '\n';
553         }
554         
555         
556         if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
557                 return '*';
558         }
559         
560         if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
561                 return '\t';
562         }
563         
564         /* comma to period */
565         char commatoperiod[] = ",-.";
566         char commatoperiodshifted[] = "<_>";
567         if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
568                 if (shifted) {
569                         return commatoperiodshifted[0];
570                 } else {
571                         return commatoperiod[0];
572                 }
573         }
574         if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
575                 if (shifted) {
576                         return commatoperiodshifted[1];
577                 } else {
578                         return commatoperiod[1];
579                 }
580         }
581         if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
582                 if (shifted) {
583                         return commatoperiodshifted[2];
584                 } else {
585                         return commatoperiod[2];
586                 }
587         }
588         
589         /* semicolon to rightbracket */
590         char semicolontorightbracket[] = ";\'`/\\=[]";
591         char semicolontorightbracketshifted[] = ":\"~\?|+{}";
592         if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
593                 && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
594                 if (shifted) {
595                         return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
596                 } else {
597                         return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
598                 }
599         }
600         
601         /* keypad2 to padplus */
602         char pad2topadplus[] = "246813579. 0- +";
603         if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
604                 && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
605                 return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
606         }
607
608         return '!';
609 }
610
611
612
613 /**
614  * Determine whether this character can be printed. We cannot use
615  * the library functions here, because we need to test our own
616  * keycodes. */
617 bool IsPrintable(int keyIndex)
618 {
619         /* only print 
620          * - numerals: KX_ZEROKEY to KX_NINEKEY
621          * - alphas:   KX_AKEY to KX_ZKEY. 
622          * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
623          *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
624          *             KX_PAD2 to KX_PADPLUSKEY
625          * - delete and backspace: also printable in the sense that they modify 
626          *                         the string
627          * - retkey: should this be printable?
628          * - virgule: prints a space... don't know which key that's supposed
629          *   to be...
630          */
631         if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
632                   && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
633                  || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
634                          && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
635                  || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
636                  || (keyIndex == SCA_IInputDevice::KX_RETKEY)
637                  || (keyIndex == SCA_IInputDevice::KX_PADENTER)
638                  || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
639                  || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
640                  || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
641                          && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
642                  || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
643                          && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
644                  || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
645                          && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
646                  || (keyIndex == SCA_IInputDevice::KX_DELKEY)
647                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)
648                 )
649         {
650                 return true;
651         } else {
652                 return false;
653         }
654 }
655
656 /**
657  * Tests whether this is a delete key.
658  */     
659 bool IsDelete(int keyIndex)
660 {
661         if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
662                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
663                 return true;
664         } else {
665                 return false;
666         }
667 }