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

events.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           mousesdl.cpp  -  description
00003                              -------------------
00004     begin                : Sun Dec 19 1999
00005     copyright            : (C) 1999 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 
00019 
00020 #include <queue>
00021 #include <SDL.h>
00022 #include <SDL_thread.h>
00023 
00024 #include "ctype.h"
00025 
00026 #include "../events.h"
00027 #include "../stack.h"
00028 #include "../basegfx.h"
00029 #include "../global.h"
00030 // #include "keysymbols.h"
00031 #include "../errors.h"
00032 #include "../messaginghub.h"
00033 #include "graphicsqueue.h"
00034 
00035 volatile tmousesettings mouseparams;
00036 
00037 SDL_mutex* keyboardmutex = NULL;
00038 SDL_mutex* eventHandlingMutex = NULL;
00039 SDL_mutex* eventQueueMutex = NULL;
00040 SDL_mutex* graphicsQueueMutex = NULL;
00041 
00042 queue<tkey>   keybuffer_sym;
00043 queue<Uint32> keybuffer_prnt;
00044 queue<SDL_Event> eventQueue;
00045 bool _queueEvents = true;
00046 bool _fillLegacyEventStructures = false;
00047 
00048 volatile bool eventThreadRunning = false;
00049 
00050 
00051 std::list<GraphicsQueueOperation*> graphicsQueue;
00052 
00053 int exitprogram = 0;
00054 
00055 
00056 /***************************************************************************
00057  *                                                                         *
00058  *   Mouse handling routines                                               *
00059  *                                                                         *
00060  ***************************************************************************/
00061 
00062 
00063 bool redrawScreen = false;
00064 
00065 const bool trueflag = true;
00066 
00067 const bool* mouseUpdateFlag = &trueflag;
00068 
00069 void setMouseUpdateFlag( const bool* flag )
00070 {
00071    mouseUpdateFlag = flag;
00072 }
00073 
00074 
00075 void mousevisible( int an)
00076 {}
00077 
00078 
00079 int getmousestatus ()
00080 {
00081    return 2;
00082 }
00083 
00084 int mouseTranslate ( int m)
00085 {
00086 
00087    const int mousetranslate[3] = {
00088       0, 2,1
00089    } ;  // in DOS  right button is 1 and center is 2
00090 
00091    if ( m >= 3 )
00092       return m;
00093    else
00094       return mousetranslate[m];
00095 }
00096 
00097 
00098 
00099 void setmouseposition ( int x, int y )
00100 {}
00101 
00102 
00103 
00104 void setnewmousepointer ( void* picture, int hotspotx, int hotspoty )
00105 {}
00106 
00107 
00108 int mouseinrect ( int x1, int y1, int x2, int y2 )
00109 {
00110    if ( mouseparams.x >= x1  && mouseparams.y >= y1  && mouseparams.x <= x2 && mouseparams.y <= y2 )
00111       return 1;
00112    else
00113       return 0;
00114 }
00115 
00116 int mouseinrect ( const tmouserect* rect )
00117 {
00118    if ( mouseparams.x >= rect->x1  && mouseparams.y >= rect->y1  && mouseparams.x <= rect->x2 && mouseparams.y <= rect->y2 )
00119       return 1;
00120    else
00121       return 0;
00122 }
00123 
00124 
00125 
00126 tmouserect tmouserect :: operator+ ( const tmouserect& b ) const
00127 {
00128    tmouserect c;
00129    c.x1 = x1 + b.x1;
00130    c.y1 = y1 + b.y1;
00131    c.x2 = x2 + b.x2;
00132    c.y2 = y2 + b.y2;
00133    return c;
00134 }
00135 
00136 
00137 
00138 /***************************************************************************
00139  *                                                                         *
00140  *   Keyboard handling routines                                            *
00141  *                                                                         *
00142  ***************************************************************************/
00143 
00144 
00145 
00146 int keypress( void )
00147 {
00148    int result = 0;
00149    int r = SDL_mutexP ( keyboardmutex );
00150    if ( !r ) {
00151       result = !keybuffer_sym.empty ( );
00152       r = SDL_mutexV ( keyboardmutex );
00153    }
00154    return result;
00155 }
00156 
00157 
00158 tkey r_key(void)
00159 {
00160    int found = 0;
00161    tkey key;
00162    do {
00163       int r = SDL_mutexP ( keyboardmutex );
00164       if ( !r ) {
00165          if ( !keybuffer_sym.empty() ) {
00166             key = keybuffer_sym.front();
00167             keybuffer_sym.pop();
00168             keybuffer_prnt.pop();
00169             found++;
00170          }
00171          r = SDL_mutexV ( keyboardmutex );
00172       }
00173       if (!found ) {
00174          int t = ticker;
00175          while ( t + 5 > ticker )
00176             releasetimeslice();
00177       }
00178    } while ( !found );
00179    return key;
00180 }
00181 
00182 int rp_key(void)
00183 {
00184    int found = 0;
00185    tkey key;
00186    do {
00187       int r = SDL_mutexP ( keyboardmutex );
00188       if ( !r ) {
00189          if ( !keybuffer_prnt.empty() ) {
00190             key = keybuffer_prnt.front();
00191             keybuffer_sym.pop();
00192             keybuffer_prnt.pop();
00193             found++;
00194          }
00195          r = SDL_mutexV ( keyboardmutex );
00196       }
00197       if (!found ) {
00198          int t = ticker;
00199          while ( t + 5 > ticker )
00200             releasetimeslice();
00201       }
00202    } while ( !found );
00203    return key;
00204 }
00205 
00206 void getkeysyms ( tkey* keysym, int* keyprnt )
00207 {
00208    int found = 0;
00209    do {
00210       int r = SDL_mutexP ( keyboardmutex );
00211       if ( !r ) {
00212          if ( !keybuffer_prnt.empty() ) {
00213             *keysym = keybuffer_sym.front();
00214             *keyprnt = keybuffer_prnt.front();
00215             keybuffer_sym.pop();
00216             keybuffer_prnt.pop();
00217             found++;
00218          }
00219          r = SDL_mutexV ( keyboardmutex );
00220       }
00221       if (!found ) {
00222          int t = ticker;
00223          while ( t + 5 > ticker )
00224             releasetimeslice();
00225       }
00226    } while ( !found );
00227 }
00228 
00229 
00230 char  skeypress(tkey keynr)
00231 {
00232    Uint8 *keystate = SDL_GetKeyState ( NULL );
00233    return keystate[ keynr ];
00234 }
00235 
00236 
00237 
00238 
00239 void wait(void)
00240 {}
00241 
00242 
00243 
00244 tkey char2key(int c )
00245 {
00246    if ( c < 128 )
00247       return tolower(c);
00248    else
00249       return ct_invvalue;
00250 }
00251 
00252 
00253 int  releasetimeslice( void )
00254 {
00255    SDL_Delay(10);
00256    if ( redrawScreen ) {
00257       redrawScreen = false;
00258       copy2screen();
00259    }
00260    return 0;
00261 }
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 /***************************************************************************
00271  *                                                                         *
00272  *   Timer routines                                                        *
00273  *                                                                         *
00274  ***************************************************************************/
00275 
00276 
00277 
00278 volatile int  ticker = 0; // was static, but I think this needs to be global somewhere
00279 
00280 void ndelay(int time)
00281 {
00282    long l;
00283 
00284    l = ticker;
00285    do {
00286       releasetimeslice();
00287    }  while (ticker - l > time);
00288 }
00289 
00290 
00291 int tticker = 0;
00292 
00293 void starttimer(void)
00294 {
00295    tticker = ticker;
00296 }
00297 
00298 char time_elapsed(int time)
00299 {
00300    if (tticker + time <= ticker) return 1;
00301    else return 0;
00302 }
00303 
00304 
00305 
00306 /***************************************************************************
00307  *                                                                         *
00308  *   Event handling routines                                               *
00309  *                                                                         *
00310  ***************************************************************************/
00311 
00312 #include <iostream>
00313 
00314 volatile int closeEventThread = 0;
00315 
00316 const int keyTranslationNum = 7;
00317 int keyTranslation[keyTranslationNum][2] = { { 228, 132 }, //   "a
00318                                              { 246, 148 }, //   "o
00319                                              { 252, 129 }, //   "u
00320                                              { 196, 142 }, //   "A
00321                                              { 214, 153 }, //   "O
00322                                              { 220, 154 }, //   "U
00323                                              { 223, 225 } }; // sz
00324 
00325 int processEvents ( )
00326 {
00327    SDL_mutexP ( eventHandlingMutex );
00328 
00329    SDL_Event event;
00330    int result;
00331    if ( SDL_PollEvent ( &event ) == 1) {
00332       if ( _fillLegacyEventStructures ) {
00333         switch ( event.type ) {
00334          case SDL_MOUSEBUTTONUP:
00335          case SDL_MOUSEBUTTONDOWN:
00336             {
00337                int taste = mouseTranslate(event.button.button - 1);
00338                int state = event.button.type == SDL_MOUSEBUTTONDOWN;
00339                if ( state )
00340                   mouseparams.taste |= (1 << taste);
00341                else
00342                   mouseparams.taste &= ~(1 << taste);
00343                mouseparams.x = event.button.x;
00344                mouseparams.y = event.button.y;
00345             }
00346             break;
00347 
00348          case SDL_MOUSEMOTION:
00349             {
00350                mouseparams.x = event.motion.x;
00351                mouseparams.y = event.motion.y;
00352                mouseparams.x1 = event.motion.x;
00353                mouseparams.y1 = event.motion.y;
00354                mouseparams.taste = 0;
00355                for ( int i = 0; i < 3; i++ )
00356                   if ( event.motion.state & (1 << i) )
00357                      mouseparams.taste |= 1 << mouseTranslate(i);
00358             }
00359             break;
00360          case SDL_KEYDOWN:
00361             {
00362                int r = SDL_mutexP ( keyboardmutex );
00363                if ( !r ) {
00364                   tkey key = event.key.keysym.sym;
00365                   if ( event.key.keysym.mod & KMOD_ALT )
00366                      key |= ct_altp;
00367                   if ( event.key.keysym.mod & KMOD_CTRL )
00368                      key |= ct_stp;
00369                   if ( event.key.keysym.mod & KMOD_SHIFT )
00370                      key |= ct_shp;
00371                   keybuffer_sym.push ( key );
00372 
00373                   int newsym = event.key.keysym.unicode;
00374                   for ( int i = 0; i < keyTranslationNum; i++ )
00375                      if ( event.key.keysym.unicode == keyTranslation[i][0] )
00376                         newsym = keyTranslation[i][1];
00377                   keybuffer_prnt.push ( newsym );
00378                   r = SDL_mutexV ( keyboardmutex );
00379                }
00380             }
00381             break;
00382          case SDL_KEYUP:
00383          {}
00384             break;
00385 
00386          case SDL_QUIT:
00387             exitprogram = 1;
00388             break;
00389 #ifdef _WIN32_
00390          case SDL_ACTIVEEVENT: 
00391             redrawScreen = true;
00392             break;
00393 #endif
00394         } 
00395       } else {
00396 #ifdef _WIN32_
00397          if ( event.type  == SDL_ACTIVEEVENT ) {
00398             queueOperation( new UpdateRectOp( SDL_GetVideoSurface(), 0,0,0,0), false, true );
00399          }
00400 #endif
00401 
00402       }
00403       result = 1;
00404       if ( _queueEvents ) {
00405          SDL_mutexP( eventQueueMutex );
00406          eventQueue.push ( event );
00407          SDL_mutexV( eventQueueMutex );
00408       }
00409 
00410 
00411    } else
00412       result = 0;
00413 
00414    SDL_mutexV( eventHandlingMutex );
00415    return result;
00416 }
00417 
00418 #if defined(_WIN32_) || defined(__APPLE__)
00419 #define FirstThreadEvents 1
00420 #endif
00421 
00422 bool syncGraphics = true;
00423 
00424 
00425 SigC::Signal1<void,const SDL_Surface*> postScreenUpdate;
00426 
00427 void queueOperation( GraphicsQueueOperation* gqo, bool wait, bool forceAsync )
00428 {
00429    if ( !eventThreadRunning ) {
00430       gqo->execute();
00431       delete gqo;
00432       return;
00433    }
00434 
00435    SDL_mutexP( graphicsQueueMutex );
00436    graphicsQueue.push_back( gqo );
00437    SDL_mutexV( graphicsQueueMutex );
00438 
00439    if ( forceAsync )
00440       return;
00441 
00442    if ( syncGraphics || wait ) {
00443       bool finished = false;
00444       do {
00445          SDL_Delay(10);
00446          SDL_mutexP( graphicsQueueMutex );
00447          finished = graphicsQueue.empty();
00448          SDL_mutexV( graphicsQueueMutex );
00449       } while (!finished);
00450    }
00451 }
00452 
00453 
00454 void UpdateRectOp::execute()
00455 { 
00456    if ( *mouseUpdateFlag )
00457       SDL_ShowCursor( 0 );
00458 
00459    SDL_UpdateRect( screen, x,y,w,h); 
00460    postScreenUpdate( screen );
00461 
00462    if ( *mouseUpdateFlag )
00463       SDL_ShowCursor( 1 );
00464 };
00465 
00466 
00467 UpdateRectsOp::UpdateRectsOp( SDL_Surface *screen, int numrects, SDL_Rect *rects) 
00468 {
00469    this->numrects = numrects;
00470    this->rects = new SDL_Rect[numrects];
00471    for ( int i = 0; i< numrects; ++i )
00472       this->rects[i] = rects[i];
00473    this->screen = screen;
00474 };
00475 
00476 UpdateRectsOp::~UpdateRectsOp()
00477 {
00478    delete[] rects;
00479 }
00480 
00481 void UpdateRectsOp::execute() 
00482 { 
00483    if ( *mouseUpdateFlag )
00484       SDL_ShowCursor( 0 );
00485 
00486    SDL_UpdateRects( screen, numrects, rects); 
00487    postScreenUpdate( screen );
00488 
00489    if ( *mouseUpdateFlag )
00490       SDL_ShowCursor( 1 );
00491 }
00492 
00493 
00494 void InitScreenOp::execute() 
00495 { 
00496    if ( *mouseUpdateFlag )
00497       SDL_ShowCursor( 0 );
00498 
00499    SDL_Surface* screen = SDL_SetVideoMode(x, y, depth, flags);
00500    if (screen == NULL) 
00501       screen = SDL_SetVideoMode(x, y, depth, flags & ~SDL_FULLSCREEN );
00502 
00503    srf( screen );
00504    initASCGraphicSubsystem( screen );
00505 
00506    if ( *mouseUpdateFlag )
00507       SDL_ShowCursor( 1 );
00508 };
00509 
00510 
00511 bool processGraphicsQueue()
00512 {
00513 #ifdef FirstThreadEvents
00514    GraphicsQueueOperation* gqo = NULL;
00515    SDL_mutexP( graphicsQueueMutex );
00516    if ( !graphicsQueue.empty() ) {
00517       gqo = graphicsQueue.front();
00518       SDL_mutexV( graphicsQueueMutex );
00519       if ( gqo ) {
00520          gqo->execute();
00521 
00522          SDL_mutexP( graphicsQueueMutex );
00523          graphicsQueue.pop_front();
00524          SDL_mutexV( graphicsQueueMutex );
00525          delete gqo;
00526          return true;
00527       } else
00528          return false;
00529    } else {
00530       SDL_mutexV( graphicsQueueMutex );
00531       return false;   
00532    }
00533 #else
00534    return false;
00535 #endif
00536 }
00537 
00538 int eventthread ( void* nothing )
00539 {
00540 #ifdef FirstThreadEvents
00541    eventThreadRunning = true;
00542 #endif
00543    while ( !closeEventThread ) {
00544       if ( !processEvents() )
00545          SDL_Delay(10);
00546       processGraphicsQueue();
00547       ticker = getTicker();
00548    }
00549 #ifdef FirstThreadEvents
00550    eventThreadRunning = false;
00551    while ( processGraphicsQueue() ) 
00552       SDL_Delay(10);
00553 #endif
00554    return closeEventThread;
00555 }
00556 
00557 
00558 int getTicker()
00559 {
00560    return SDL_GetTicks() / 10;
00561 }
00562 
00563 #ifdef FirstThreadEvents 
00564 int (*_gamethread)(void *);
00565 
00566 int gameThreadWrapper ( void* data )
00567 {
00568    try {
00569       int res = _gamethread ( data );
00570       closeEventThread = 1;
00571       return res;
00572    }
00573 #ifndef WIN32
00574    catch ( ... ) {
00575       fatalError ("An unhandled exception occured. Quitting application");
00576    }
00577 #else
00578    catch ( ASCexception ) {
00579       fatalError ("An unhandled exception occured. Quitting application");
00580    }
00581 #endif
00582    closeEventThread = -1;
00583    return -1;
00584 }
00585 #endif
00586 
00587 
00589 SDL_Thread* secondThreadHandle = NULL;
00590 
00591 
00592 
00593 int initializeEventHandling ( int (*gamethread)(void *) , void *data )
00594 {
00595 
00596    mouseparams.xsize = 10;
00597    mouseparams.ysize = 10;
00598 
00599    keyboardmutex = SDL_CreateMutex ();
00600    if ( !keyboardmutex ) {
00601       printf("creating keyboard mutex failed\n" );
00602       exit(1);
00603    }
00604 
00605    eventHandlingMutex = SDL_CreateMutex ();
00606    if ( !eventHandlingMutex ) {
00607       printf("creating eventHandling mutex failed\n" );
00608       exit(1);
00609    }
00610 
00611 
00612    eventQueueMutex = SDL_CreateMutex ();
00613    if ( !eventQueueMutex ) {
00614       printf("creating eventQueueMutex failed\n" );
00615       exit(1);
00616    }
00617 
00618    graphicsQueueMutex = SDL_CreateMutex();
00619    if ( !graphicsQueueMutex ) {
00620       printf("creating graphicsQueueMutex failed\n" );
00621       exit(1);
00622    }
00623 
00624    SDL_EnableUNICODE ( 1 );
00625    SDL_EnableKeyRepeat ( 250, 30 );
00626 
00627    
00628 #ifdef FirstThreadEvents 
00629    _gamethread = gamethread;
00630    secondThreadHandle = SDL_CreateThread ( gameThreadWrapper, data );
00631    int res = eventthread( NULL );
00632 #else
00633    secondThreadHandle = SDL_CreateThread ( eventthread, NULL );
00634    int res = gamethread( data );
00635    closeEventThread = 1;
00636 #endif
00637 
00638 
00639    SDL_WaitThread ( secondThreadHandle, NULL );
00640    return res;
00641 }
00642 
00643 
00644 
00645 void exit_asc( int returnresult )
00646 {
00647 #ifndef FirstThreadEvents 
00648    if ( secondThreadHandle ) {
00649       closeEventThread = 1;
00650       SDL_WaitThread ( secondThreadHandle, NULL );
00651    }   
00652    exit( returnresult );   
00653 #else
00654    if ( secondThreadHandle ) {
00655       throw ThreadExitException();
00656    }
00657    exit( returnresult );   
00658 
00659 
00660 #endif
00661 
00662    
00663 }
00664 
00665 
00666 bool setEventRouting( bool queue, bool legacy )
00667 {
00668   bool prev = _queueEvents;
00669   
00670   _fillLegacyEventStructures = legacy;
00671   
00672   _queueEvents = queue;
00673   if ( !queue ) {
00674       // clear all waiting events in the queue
00675       SDL_mutexP( eventQueueMutex );
00676       while ( !eventQueue.empty())
00677          eventQueue.pop();
00678       SDL_mutexV( eventQueueMutex );
00679    }
00680    
00681    return prev;
00682 }
00683 
00684 bool legacyEventSystemActive()
00685 {
00686    return _fillLegacyEventStructures;   
00687 }
00688 
00689 
00690 bool getQueuedEvent ( SDL_Event& event )
00691 {
00692    SDL_mutexP( eventQueueMutex );
00693    if ( !eventQueue.empty() ) {
00694       event = eventQueue.front();
00695       eventQueue.pop();
00696       SDL_mutexV( eventQueueMutex );
00697       return true;
00698    }
00699    SDL_mutexV( eventQueueMutex );
00700    return false;
00701 }
00702     
00703 bool peekEvent ( SDL_Event& event )
00704 {
00705    SDL_mutexP( eventQueueMutex );
00706    if ( !eventQueue.empty() ) {
00707       event = eventQueue.front();
00708       SDL_mutexV( eventQueueMutex );
00709       return true;
00710    }
00711    SDL_mutexV( eventQueueMutex );
00712    return false;
00713 }
00714 
00715 

Generated on Tue Jun 24 01:27:41 2008 for Advanced Strategic Command by  doxygen 1.4.2