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