Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArKeyHandler.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArKeyHandler.h"
00030 #include "ArLog.h"
00031 
00032 #ifdef WIN32
00033 #include <conio.h>
00034 #else // if not win32
00035 #include <stdio.h>
00036 #endif
00037 
00038 #include "ArRobot.h"
00039 #include "ariaInternal.h"
00040 
00047 ArKeyHandler::ArKeyHandler(bool blocking, bool addAriaExitCB) :
00048   myAriaExitCB(this, &ArKeyHandler::restore)
00049 {
00050   myAriaExitCB.setName("ArKeyHandlerExit");
00051   if (addAriaExitCB)
00052     Aria::addExitCallback(&myAriaExitCB);
00053   takeKeys(blocking);
00054 }
00055 
00056 ArKeyHandler::~ArKeyHandler()
00057 {
00058   restore();
00059 }
00060 
00061 void ArKeyHandler::takeKeys(bool blocking)
00062 {
00063   myBlocking = blocking;
00064 #ifndef WIN32
00065   struct termios newTermios;
00066 
00067   tcgetattr(fileno(stdin), &myOriginalTermios);
00068   
00069   tcgetattr(fileno(stdin), &newTermios);
00070   
00071   newTermios.c_cc[VTIME] = 0;
00072   if (myBlocking)
00073     newTermios.c_cc[VMIN] = 1;
00074   else
00075     newTermios.c_cc[VMIN] = 0;
00076   newTermios.c_lflag &= (~ECHO & ~ICANON);
00077   tcsetattr(fileno(stdin), TCSANOW, &newTermios);
00078 
00079 #endif
00080   myRestored = false;
00081 }
00082 
00083 void ArKeyHandler::restore(void)
00084 {
00085 #ifndef WIN32
00086   tcsetattr(fileno(stdin), TCSANOW, &myOriginalTermios);
00087 
00088 #endif
00089   myRestored = true;
00090 }
00091 
00103 bool ArKeyHandler::addKeyHandler(int keyToHandle, ArFunctor *functor)
00104 {
00105   if (myMap.find(keyToHandle) != myMap.end())
00106   {
00107     ArLog::log(ArLog::Normal, "There is already a key to handle '%c' which is number %d 0x%x", keyToHandle, keyToHandle, keyToHandle);
00108     return false;
00109   }
00110   //ArLog::log(ArLog::Verbose, "keyhandler %p added key '%c' number '%d'", 
00111   //this, keyToHandle, keyToHandle);
00112   myMap[keyToHandle] = functor;
00113 
00114   return true;
00115 }
00116 
00125 bool ArKeyHandler::remKeyHandler(int keyToHandle)
00126 {
00127   if (myMap.find(keyToHandle) == myMap.end())
00128   {
00129     //ArLog::log(ArLog::Normal, "There is no key to handle '%c' which is number %d 0x%x", keyToHandle, keyToHandle, keyToHandle);
00130     return false;
00131   }
00132   ArLog::log(ArLog::Verbose, "keyhandler %p removed key '%c' number '%d'",
00133              this, keyToHandle, keyToHandle);
00134   myMap.erase(keyToHandle);
00135   return true;
00136 }
00137 
00145 bool ArKeyHandler::remKeyHandler(ArFunctor *functor)
00146 {
00147   std::map<int, ArFunctor *>::iterator it;
00148   std::list<std::map<int, ArFunctor *>::iterator> iters;
00149   std::list<std::map<int, ArFunctor *>::iterator>::iterator iterIter;
00150 
00151   for (it = myMap.begin(); it != myMap.end(); ++it)
00152   {
00153     if (it->second == functor)
00154     {
00155       iters.push_front(it);
00156     }
00157   }
00158   if (iters.size() > 0)
00159   {
00160     while((iterIter = iters.begin()) != iters.end())
00161     {
00162       myMap.erase((*iterIter));
00163       iters.pop_front();
00164     }
00165     ArLog::log(ArLog::Verbose, "keyhandler %p removed functor %p", this, 
00166                functor);
00167     return true;
00168   }
00169   return false;
00170 }
00171 
00172 void ArKeyHandler::checkKeys(void)
00173 {
00174   int key;
00175   std::map<int, ArFunctor *>::iterator it;
00176 
00177   if (myRestored)
00178     return;
00179 
00180   // get keys until they're gone
00181   while (!myRestored && (key = getKey()) != -1)
00182   {
00183     // if there's something to handle it, handle it
00184     if ((it = myMap.find(key)) != myMap.end())
00185     {
00186       //ArLog::log(ArLog::Verbose, "key '%c' num %d pressed\n", key, key);
00187       it->second->invoke();
00188     }
00189   }
00190 }
00191 
00192 #ifndef WIN32
00193 
00194 int ArKeyHandler::getKey(void)
00195 {
00196  /*
00197   * What follows is a very poor implementation of getch(), basically, since
00198   * we want to get control keys but don't want to have to use curses.
00199   */
00200 
00201   int key;
00202   int k[5] = {-1, -1, -1, -1, -1};   // used for escape sequences
00203 
00204   key = getchar();
00205   switch(key)
00206   {
00207     case -1:
00208     case 0:
00209       return -1;
00210 
00211     //case -1: return ESCAPE; //?
00212     case ' ': return SPACE;
00213     case '\t': return TAB;
00214     case 10: return ENTER;
00215     case 8: return BACKSPACE;
00216     case 127: return BACKSPACE;
00217 
00218     case 27: // Escape key, or Begin special control key sequence
00219       key = getchar();
00220       switch(key)
00221       {
00222         case -1: return ESCAPE;
00223         case 79: // first four F keys
00224           key = getchar();
00225           switch(key)
00226           {
00227             case 80: return F1;
00228             case 81: return F2;
00229             case 82: return F3;
00230             case 83: return F4;
00231             case 70: return END;
00232             case 72: return HOME;
00233             default: return key;
00234           }
00235         case '[':  // keypad keys and extended F-key sequences start with this 
00236           // Read in all characters in the special key sequence. -1 is the
00237           // terminator (no more keys). We also check for the beginning of a new special key
00238           // sequence (27) since if the key repeat is high enough, they begin
00239           // overlapping. TODO: check trailing keys for modifiers and set an
00240           // (optional parameter) bitmask.
00241           for(short i = 0; key != -1 && key != 27 && i < 5; i++) 
00242           {
00243             k[i] = key = getchar();
00244             //printf("ArKeyHandler::getKey: read extended key component %d/%d.\n", k[i], key);
00245           }
00246           ungetc(key, stdin); // put last key back. (Esp. important if it was the beginning of a new control sequence (27).
00247 
00248           switch(k[0])
00249           {
00250             case 65: return UP;
00251             case 66: return DOWN;
00252             case 67: return RIGHT;
00253             case 68: return LEFT; 
00254 
00255             case 51: return DEL;
00256             case 53: return PAGEUP;
00257             case 54: return PAGEDOWN;
00258 
00259             case 50: 
00260               switch(k[1])
00261               {
00262                 case 126: return INSERT;
00263                 case 48:  return F9;
00264                 case 49:  return F10;
00265                 case 51:  return F11;
00266                 case 52:  return F12;
00267               }
00268               return k[1];
00269 
00270 
00271             case 49:
00272               switch(k[1])
00273               {
00274                 case 53: return F5;
00275                 case 55: return F6;
00276                 case 56: return F7;
00277                 case 57: return F8;
00278               }
00279               return k[1];
00280             default: return -1;
00281           }
00282         default: return -1;
00283       }
00284 
00285     default: return key;
00286   }
00287 }
00288 
00289 #if 0
00290 /* This is a previous implementation of Unix getKey(), just for reference or
00291  * quick reversion: */
00292 int ArKeyHandler::getKey(void)
00293 {
00294   char key;
00295 
00296   key = getchar();
00297   if (key == -1 || key == 0)
00298       return -1;
00299 
00300   if (key == 27)
00301   {
00302     key = getchar();
00303     if (key == '[')
00304     {
00305       key = getchar();
00306       if (key == 'A')
00307         return UP;
00308       else if (key == 'B')
00309         return DOWN;
00310       else if (key == 'C')
00311         return RIGHT;
00312       else if (key == 'D')
00313         return LEFT;
00314       else
00315         return getKey();
00316     }
00317     else if (key == -1)
00318       return ESCAPE;
00319     else if (key == 79)
00320     {
00321        key = getchar();
00322        if (key == 'P')
00323          return F1;
00324        else if (key == 'Q')
00325          return F2;
00326        else if (key == 'R')
00327          return F3;
00328        else if (key == 'S')
00329          return F4;
00330        else
00331          return getKey();
00332     }
00333   }
00334   else if (key == ' ')
00335     return SPACE;
00336   else if (key == '\t')
00337     return TAB;
00338   else if (key == 10)
00339     return ENTER;
00340   else if (key == 8 || key == 127)
00341     return BACKSPACE;
00342   return key;
00343 }
00344 #endif
00345 
00346 
00347 #else // if it is win32
00348 
00349 int ArKeyHandler::getKey(void)
00350 {
00351   int key;
00352 
00353   if (!myBlocking && !kbhit())
00354     return -1;
00355 
00356   key = _getch();
00357   if (key == 224)
00358   {
00359     key = _getch();
00360     if (key == 'H')
00361       return UP;
00362     else if (key == 'P')
00363       return DOWN;
00364     else if (key == 'K')
00365       return LEFT;
00366     else if (key == 'M')
00367       return RIGHT;
00368     else 
00369       return getKey();
00370   }
00371   else if (key == 0)
00372   {
00373     key = _getch();
00374     if (key == ';')
00375       return F1;
00376     else if (key == '<')
00377       return F2;
00378     else if (key == '=')
00379       return F3;
00380     else if (key == '>')
00381       return F4;
00382     else if (key == 'H')
00383       return UP;
00384     else if (key == 'P')
00385       return DOWN;
00386     else if (key == 'K')
00387       return LEFT;
00388     else if (key == 'M')
00389       return RIGHT;
00390     else
00391       return getKey();
00392   }
00393   else if (key == ' ')
00394     return SPACE;
00395   else if (key == '\t')
00396     return TAB;
00397   else if (key == 13)
00398     return ENTER;
00399   else if (key == 8)
00400     return BACKSPACE;
00401   else if (key == 27)
00402         return ESCAPE;
00403 
00404   return key;
00405 
00406 }
00407 
00408 #endif // WIN32
00409 

Generated on Wed Oct 19 12:56:36 2005 for Aria by  doxygen 1.4.0