1 /*
2 *
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
7 *
8 * See LICENSING which should be included
9 * along with this file for more details
10 *
11 */
12
13 #include <cstdio>
14 #include <ctime>
15 #include <ratio>
16 #include <chrono>
17
18 #include "bitmap.h"
19 #include "error.h"
20 #include "graphics.h"
21 #include "festring.h"
22 #include "rawbit.h"
23 #include "whandler.h"
24
25 #include "dbgmsgproj.h"
26
27 #if SDL_MAJOR_VERSION == 1
28 /* redefine SDL2 to SDL1 */
29 #define SDL_WINDOWEVENT SDL_VIDEOEXPOSE
30 #define SDLK_PRINTSCREEN SDLK_PRINT
31 #define SDLK_KP_0 SDLK_KP0
32 #define SDLK_KP_1 SDLK_KP1
33 #define SDLK_KP_2 SDLK_KP2
34 #define SDLK_KP_3 SDLK_KP3
35 #define SDLK_KP_4 SDLK_KP4
36 #define SDLK_KP_5 SDLK_KP5
37 #define SDLK_KP_6 SDLK_KP6
38 #define SDLK_KP_7 SDLK_KP7
39 #define SDLK_KP_8 SDLK_KP8
40 #define SDLK_KP_9 SDLK_KP9
41 #endif
42
43 truth (*globalwindowhandler::ControlLoop[MAX_CONTROLS])();
44 int globalwindowhandler::Controls = 0;
45 ulong globalwindowhandler::Tick;
46 truth globalwindowhandler::ControlLoopsEnabled = true;
47 truth globalwindowhandler::playInBackground=false;
48 festring globalwindowhandler::ScrshotDirectoryName = "";
49 truth bLastSDLkeyEventIsKeyUp=false;
50
InstallControlLoop(truth (* What)())51 void globalwindowhandler::InstallControlLoop(truth (*What)())
52 {
53 if(Controls == MAX_CONTROLS)
54 ABORT("Animation control frenzy!");
55
56 ControlLoop[Controls++] = What;
57 }
58
DeInstallControlLoop(truth (* What)())59 void globalwindowhandler::DeInstallControlLoop(truth (*What)())
60 {
61 int c;
62
63 for(c = 0; c < Controls; ++c)
64 if(ControlLoop[c] == What)
65 break;
66
67 if(c != Controls)
68 {
69 --Controls;
70
71 for(; c < Controls; ++c)
72 ControlLoop[c] = ControlLoop[c + 1];
73 }
74 }
75
IsKeyPressed(int iSDLScanCode)76 bool globalwindowhandler::IsKeyPressed(int iSDLScanCode)
77 {
78 return SDL_GetKeyboardState(NULL)[iSDLScanCode];
79 }
80
81
82 #ifdef __DJGPP__
83
84 #include <pc.h>
85 #include <keys.h>
86
GetKey(truth EmptyBuffer)87 int globalwindowhandler::GetKey(truth EmptyBuffer)
88 {
89 if(EmptyBuffer)
90 while(kbhit())
91 getkey();
92
93 int Key = 0;
94
95 while(!Key)
96 {
97 while(!kbhit())
98 if(Controls && ControlLoopsEnabled)
99 {
100 static ulong LastTick = 0;
101 UpdateTick();
102
103 if(LastTick != Tick)
104 {
105 LastTick = Tick;
106 truth Draw = false;
107
108 for(int c = 0; c < Controls; ++c)
109 if(ControlLoop[c]())
110 Draw = true;
111
112 if(Draw)
113 graphics::BlitDBToScreen();
114 }
115 }
116
117 Key = getkey();
118
119 if(Key == K_Control_Print && !ScrshotDirectoryName.IsEmpty())
120 {
121 mkdir(ScrshotDirectoryName.CStr(), S_IRUSR|S_IWUSR);
122 DOUBLE_BUFFER->Save(ScrshotNameHandler());
123 Key = 0;
124 }
125 }
126
127 return Key;
128 }
129
ReadKey()130 int globalwindowhandler::ReadKey()
131 {
132 return kbhit() ? getkey() : 0;
133 }
134
135 #endif
136
137 #ifdef USE_SDL
138
139 #include <algorithm>
140
141 std::vector<int> globalwindowhandler::KeyBuffer;
142 truth (*globalwindowhandler::QuitMessageHandler)() = 0;
143 bool (*globalwindowhandler::FunctionKeyHandler)(SDL_Keycode) = 0;
144 bool (*globalwindowhandler::ControlKeyHandler)(SDL_Keycode) = 0;
145
Init()146 void globalwindowhandler::Init()
147 {
148 #if SDL_MAJOR_VERSION == 1
149 SDL_EnableUNICODE(1);
150 SDL_EnableKeyRepeat(500, 30);
151 #else
152 //FIXSDL2 SDL_EnableKeyRepeat(500, 30);
153 SDL_ShowWindow(graphics::GetWindow());
154 #endif
155 }
156
157 int iCountFPS=0;
158 int iLastSecondFPS=0;
159 std::chrono::high_resolution_clock::time_point tpLastSecondFPS;
MeasureLastSecondRealFPS()160 int MeasureLastSecondRealFPS(){ //call this every new frame request
161 iCountFPS++;
162
163 using namespace std::chrono;
164 high_resolution_clock::time_point tpNow = high_resolution_clock::now();
165 duration<double, std::milli> delay = tpNow - tpLastSecondFPS;
166 if(delay.count() > 1000){ //1s
167 iLastSecondFPS=iCountFPS;
168 iCountFPS=0; //reset
169 tpLastSecondFPS = tpNow; //reset
170 }
171
172 return iLastSecondFPS;
173 }
174
175 std::chrono::high_resolution_clock::time_point tpPreviousFrameTime;
InstaCalcFPS()176 double InstaCalcFPS(){ //call this every new frame request
177 using namespace std::chrono;
178 high_resolution_clock::time_point tpNow = high_resolution_clock::now();
179 duration<double, std::milli> delay = tpNow - tpPreviousFrameTime;
180 tpPreviousFrameTime = tpNow;
181 double d = delay.count();
182 if(d==0)d=1; //TODO this may never happen?
183 return 1000/d;
184 }
185
186 bool bAllowFrameSkip=true;
187 int iFrameSkip=0;
188 std::chrono::high_resolution_clock::time_point tpBefore;
189 std::chrono::duration<double, std::milli> delay;
190 int iLastSecCountFPS;
191 float fInstaFPS;
192 double dLastFrameTimeMS;
193 int iDefaultDelayMS=10;
194 int iAddFrameSkip=0;
195
SetAddFrameSkip(int i)196 void globalwindowhandler::SetAddFrameSkip(int i){
197 iAddFrameSkip=i;
198 bAllowFrameSkip = iAddFrameSkip!=0;
199 }
200
201 /**
202 * to let user input be more responsive as full dungeon xBRZ may be too heavy
203 * return SDL delay in ms
204 */
FrameSkipOrDraw()205 int FrameSkipOrDraw(){ //TODO could this be simplified?
206 bool bWaitAKeyPress=false;
207 bool bDoAutoFrameSkip=false;
208 bool bDrawFrame=false;
209 bool bDelay1MS=false;
210
211 if(iFrameSkip<0)ABORT("iFrameSkip is %d < 0",iFrameSkip);
212
213 if(iAddFrameSkip==-2){
214 if(dLastFrameTimeMS>142){ //if it is too slow <= 7 fps
215 bWaitAKeyPress=true;
216 }else{
217 bDoAutoFrameSkip=true;
218 }
219 }else
220 if(iAddFrameSkip==-1){
221 bDoAutoFrameSkip=true;
222 }
223
224 if(!bWaitAKeyPress){ // if waiting a key press, there will have no stand-by animation at all...
225 if(iFrameSkip==0){
226 bDrawFrame=true;
227
228 // setup next
229 if(bDoAutoFrameSkip){ //TODO improve this automatic mode?
230 if(dLastFrameTimeMS>250){ //4fps
231 iFrameSkip=10;
232 }else
233 if(dLastFrameTimeMS>200){ //5fps
234 iFrameSkip=5;
235 }else
236 if(dLastFrameTimeMS>150){
237 iFrameSkip=3;
238 }else
239 if(dLastFrameTimeMS>100){ //10fps
240 iFrameSkip=1;
241 }
242
243 bDelay1MS=true;
244 }else{
245 if(iAddFrameSkip==0){ //vanilla (wont be reached tho cuz of bAllowFrameSkip=false), kept for completeness (in case it changes before calling this method)
246 bDrawFrame=true;
247 }else
248 if(iAddFrameSkip>0){ //fixed
249 iFrameSkip=iAddFrameSkip;
250
251 bDelay1MS=true;
252 }
253 }
254 }
255 }
256
257 if(bDrawFrame){
258 tpBefore = std::chrono::high_resolution_clock::now();
259 graphics::BlitDBToScreen();
260 delay = std::chrono::high_resolution_clock::now() - tpBefore;
261 dLastFrameTimeMS = delay.count();
262
263 //call these ONLY when the frame is actually DRAWN!!! (despite not being actually used yet)
264 iLastSecCountFPS = MeasureLastSecondRealFPS();
265 fInstaFPS = InstaCalcFPS();
266 //DBG5(DBGF(fInstaFPS),DBGI(iLastSecCountFPS),DBGF(dLastFrameTimeMS),DBGI(iAddFrameSkip),DBGI(iFrameSkip));
267 }else{
268 if(iFrameSkip>0)iFrameSkip--;
269 //DBGSI(iFrameSkip);
270 }
271
272 if(bDelay1MS){
273 return 1;
274 }else{
275 return iDefaultDelayMS;
276 }
277 }
278
279 const int globalwindowhandler::iRestWaitKey = '.';
280
281 int iTimeoutDelay=0; // must init with 0
282 int iTimeoutDefaultKey = globalwindowhandler::iRestWaitKey;
283 long keyTimeoutRequestedAt;
284 /**
285 * This is intended to remain active ONLY until the user hits any key.
286 * iTimeoutMillis can be 0 or >=10
287 */
SetKeyTimeout(int iTimeoutMillis,int iDefaultReturnedKey)288 void globalwindowhandler::SetKeyTimeout(int iTimeoutMillis,int iDefaultReturnedKey)//,int iIgnoreKeyWhenDisabling)
289 {
290 if(iTimeoutMillis<0)ABORT("invalid negative timeout %d",iTimeoutMillis);
291
292 iTimeoutDelay = (iTimeoutMillis/1000.0) * CLOCKS_PER_SEC;
293 if(iTimeoutDelay>0 && iTimeoutDelay<10)iTimeoutDelay=10; // we are unable to issue commands if it is too low TODO could be less than 10ms?
294
295 iTimeoutDefaultKey=iDefaultReturnedKey;
296 }
IsKeyTimeoutEnabled()297 truth globalwindowhandler::IsKeyTimeoutEnabled()
298 {
299 return iTimeoutDelay>0;
300 }
CheckKeyTimeout()301 void globalwindowhandler::CheckKeyTimeout()
302 {
303 if(iTimeoutDelay>0){ // timeout mode is enalbed
304 if(!KeyBuffer.empty()){ DBG2(KeyBuffer.size(),KeyBuffer[0]); // user pressed some key
305 keyTimeoutRequestedAt=clock(); // resets reference time to wait from
306 }else{ DBG2(keyTimeoutRequestedAt,iTimeoutDelay);
307 if( clock() > (keyTimeoutRequestedAt+iTimeoutDelay) ) //wait for the timeout to...
308 KeyBuffer.push_back(iTimeoutDefaultKey); //...simulate the keypress
309 }
310 }
311 }
312 int iTimeoutDelayBkp=0;
SuspendKeyTimeout()313 void globalwindowhandler::SuspendKeyTimeout()
314 {
315 iTimeoutDelayBkp=iTimeoutDelay;
316 iTimeoutDelay=0;
317 }
ResumeKeyTimeout()318 void globalwindowhandler::ResumeKeyTimeout()
319 {
320 iTimeoutDelay=iTimeoutDelayBkp;
321 }
322
GetFPS(bool bInsta)323 float globalwindowhandler::GetFPS(bool bInsta){
324 if(bInsta)return fInstaFPS;
325 return iLastSecCountFPS;
326 }
327
HasKeysOnBuffer()328 truth globalwindowhandler::HasKeysOnBuffer(){
329 return KeyBuffer.size()>0;
330 }
331
ShowFPS()332 void ShowFPS(){ //TODO still flickers sometimes cuz of silhouette?
333 static long lTimePrevious=clock();
334 static bool bShowFPS = [](){const char* c=std::getenv("IVAN_SHOWFPS");return c!=NULL && strcmp(c,"true")==0;}();
335 if(bShowFPS){
336 // if(clock()%(CLOCKS_PER_SEC*3)<CLOCKS_PER_SEC){
337 long lTime=clock();
338 if(clock()-lTimePrevious > CLOCKS_PER_SEC*1){
339 static int iMargin=2;
340 static v2 v2Margin(iMargin,iMargin);
341 static char c[100];
342
343 sprintf(c,"FPS:ls=%.1f,insta=%.1f",globalwindowhandler::GetFPS(false),globalwindowhandler::GetFPS(true));
344 int iDistX = strlen(c)*8 + 10 + 100; // +10 to look good, + 100 cuz of silhouette area
345 v2 v2Pos = RES-v2(iDistX,RES.Y)+v2Margin;
346 v2 v2Size(iDistX, 8+iMargin*2);
347
348 DOUBLE_BUFFER->Fill(v2Pos,v2Size,BLACK);
349 FONT->Printf(DOUBLE_BUFFER,v2Pos+v2Margin,WHITE,"%s",c);
350 lTimePrevious=lTime;
351 }
352 }
353 }
354
GetKey(truth EmptyBuffer)355 int globalwindowhandler::GetKey(truth EmptyBuffer)
356 {
357 SDL_Event Event;
358
359 if(EmptyBuffer)
360 {
361 PollEvents(&Event);
362 KeyBuffer.clear();
363 }
364
365 keyTimeoutRequestedAt=clock();
366 int iDelayMS=iDefaultDelayMS;
367 for(;;){
368 CheckKeyTimeout();
369
370 if(!KeyBuffer.empty())
371 {
372 int Key = KeyBuffer[0];
373 KeyBuffer.erase(KeyBuffer.begin());
374
375 if(Key > 0xE000)
376 return Key - 0xE000;
377
378 if(Key && Key < 0x81)
379 return Key;
380 }
381 else
382 {
383 bool bHasFocus=false;
384 #if SDL_MAJOR_VERSION == 1
385 bHasFocus = SDL_GetAppState() & SDL_APPACTIVE;
386 #else
387 bHasFocus = SDL_GetWindowFlags(graphics::GetWindow()) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS);
388 #endif
389
390 bool bPlay=true;
391
392 if(bPlay && !bHasFocus && !playInBackground)
393 bPlay=false;
394
395 if(bPlay && Controls==0)
396 bPlay=false;
397
398 if(bPlay && !ControlLoopsEnabled)
399 bPlay=false;
400
401 bool bHasEvents=PollEvents(&Event)>0;
402
403 if(!bHasEvents)
404 {
405 if(bPlay)
406 {
407 static ulong LastTick = 0;
408 UpdateTick();
409
410 if(LastTick != Tick)
411 {
412 LastTick = Tick;
413 truth Draw = false;
414
415 for(int c = 0; c < Controls; ++c)
416 if(ControlLoop[c]())
417 Draw = true;
418
419 /******************
420 * the stand-by animation
421 */
422 ShowFPS();
423 if(!bAllowFrameSkip){
424 if(Draw)
425 graphics::BlitDBToScreen();
426
427 iDelayMS=iDefaultDelayMS;
428 }else{
429 iDelayMS = FrameSkipOrDraw();
430 }
431
432 }
433
434 SDL_Delay(iDelayMS);
435 }
436 else
437 {
438 if(bHasFocus){
439 iDelayMS=1000/30; //30 FPS on main menu just to not use too much CPU there. If one day it is animated, lower this properly.
440 SDL_Delay(iDelayMS);
441 }else{
442 SDL_WaitEvent(&Event);DBGLN;
443 ProcessMessage(&Event);DBGLN;
444 }
445 }
446 }
447 }
448
449 }
450 }
451
PollEvents(SDL_Event * pEvent)452 uint globalwindowhandler::PollEvents(SDL_Event* pEvent)
453 {
454 if(pEvent==NULL)
455 pEvent=new SDL_Event();
456
457 uint i=0;
458 while(SDL_PollEvent(pEvent)){
459 ProcessMessage(pEvent);
460 i++;
461 }
462
463 return i;
464 }
465
466 v2 v2MousePos;
UpdateMouse()467 uint globalwindowhandler::UpdateMouse()
468 {
469 /**
470 * global didnt fix the wrong mouse position relatively to the visible cursor...
471 if(SDL_GetWindowFlags(graphics::GetWindow()) & SDL_WINDOW_FULLSCREEN_DESKTOP)
472 return SDL_GetGlobalMouseState(&v2MousePos.X,&v2MousePos.Y);
473 else
474 */
475 return SDL_GetMouseState(&v2MousePos.X,&v2MousePos.Y);
476 }
477
ReadKey()478 int globalwindowhandler::ReadKey()
479 {
480 SDL_Event Event;
481
482 #if SDL_MAJOR_VERSION == 1
483 if(SDL_GetAppState() & SDL_APPACTIVE)
484 #else
485 if( playInBackground || (SDL_GetWindowFlags(graphics::GetWindow()) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS)) )
486 #endif
487 {
488 PollEvents(&Event);
489 }
490 else
491 {
492 SDL_WaitEvent(&Event);
493 ProcessMessage(&Event);
494 }
495
496 return KeyBuffer.size() ? GetKey(false) : 0;
497 }
498
WaitForKeyEvent(uint Key)499 truth globalwindowhandler::WaitForKeyEvent(uint Key)
500 {
501 SDL_Event Event;
502
503 #if SDL_MAJOR_VERSION == 1
504 if(SDL_GetAppState() & SDL_APPACTIVE)
505 #else
506 if( playInBackground || (SDL_GetWindowFlags(graphics::GetWindow()) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS)) )
507 #endif
508 {
509 #if SDL_MAJOR_VERSION == 2
510 while(SDL_PollEvent(&Event))
511 if(Event.type == Key)
512 return true;
513 #else
514 while(SDL_PollEvent(&Event))
515 if(Event.active.type == Key)
516 return true;
517 #endif
518 }
519 else
520 SDL_WaitEvent(&Event);
521
522 return false;
523 }
524
IsLastSDLkeyEventWasKeyUp()525 truth globalwindowhandler::IsLastSDLkeyEventWasKeyUp()
526 {
527 return bLastSDLkeyEventIsKeyUp;
528 }
529
GetMouseLocation()530 v2 globalwindowhandler::GetMouseLocation()
531 {
532 UpdateMouse();
533 return v2MousePos;
534 }
535
IsMouseAtRect(v2 v2TopLeft,v2 v2BorderOrBottomRigh,bool b2ndParmIsBorder,v2 v2MousePosOverride)536 bool globalwindowhandler::IsMouseAtRect(v2 v2TopLeft, v2 v2BorderOrBottomRigh, bool b2ndParmIsBorder, v2 v2MousePosOverride)
537 {
538 v2 v2MP = v2MousePosOverride;
539 if(v2MousePosOverride.Is0()){
540 UpdateMouse();
541 v2MP=v2MousePos;
542 }
543
544 v2 v2BottomRight = v2BorderOrBottomRigh;
545 if(b2ndParmIsBorder)
546 v2BottomRight += v2TopLeft;
547
548 return
549 v2MP.X > v2TopLeft.X &&
550 v2MP.Y > v2TopLeft.Y &&
551 v2MP.X < v2BottomRight.X &&
552 v2MP.Y < v2BottomRight.Y ;
553 }
554
555 mouseclick mc;
ConsumeMouseEvent()556 mouseclick globalwindowhandler::ConsumeMouseEvent() //TODO buffer it?
557 {
558 mouseclick mcR;
559 if(mc.btn!=-1 || mc.wheelY!=0)
560 mcR=mc;
561
562 mc.btn=-1;
563 mc.pos=v2();
564 mc.wheelY=0;
565
566 return mcR;
567 }
568
ChkCtrlKey(SDL_Event * Event)569 int globalwindowhandler::ChkCtrlKey(SDL_Event* Event)
570 {
571 if(Event->key.keysym.mod & KMOD_CTRL){ //if CTRL is pressed, user expects something else than the normal key, therefore not permissive
572 if(ControlKeyHandler!=NULL)
573 ControlKeyHandler(Event->key.keysym.sym);
574 return iRestWaitKey; //gum TODO 0 should suffice one day...
575 }DBGLN;
576
577 return Event->key.keysym.sym;
578 }
579
ProcessKeyDownMessage(SDL_Event * Event)580 void globalwindowhandler::ProcessKeyDownMessage(SDL_Event* Event)
581 {DBG4(Event->key.keysym.sym,Event->text.text[0],Event->key.keysym.mod & KMOD_ALT,Event->key.keysym.mod & KMOD_CTRL);
582
583 bLastSDLkeyEventIsKeyUp=false;
584
585 /**
586 * Events are splitted between SDL_KEYDOWN and SDL_TEXTINPUT.
587 *
588 * All managed events must be explicited,
589 * so, all keyDown events that will be modified must be handled here,
590 * all other non modified keyDown events will be handled by SDL_TEXTINPUT event type outside here.
591 *
592 * More modifiers also means higher priority.
593 *
594 * if one or more modifiers are pressed,
595 * user expects something else than the normal key,
596 * therefore wont fill the key buffer
597 *
598 * Non handled ctrl+alt+... or ctrl+... or alt+... will be ignored.
599 * Tho, they may be overriden by the OS and never reach here...
600 */
601
602 if((Event->key.keysym.mod & KMOD_CTRL) && (Event->key.keysym.mod & KMOD_ALT)){
603 switch(Event->key.keysym.sym)
604 {
605 case SDLK_e:
606 /**
607 * TODO
608 * exemplify where this is or can be ever used as tests provided no results on Linux,
609 * is it the windows Explorer key? if so #ifdef WIN32 should be used...
610 */
611 AddKeyToBuffer('\177');
612 break;
613 }
614 return;
615 }
616
617 if(Event->key.keysym.mod & KMOD_CTRL){ //TODO right control key is being ignored on lists for ctrl+f filter on the first try
618 if(ControlKeyHandler!=NULL) //this one was completely externalized
619 ControlKeyHandler(Event->key.keysym.sym);
620 return;
621 }else
622 if(Event->key.keysym.mod & KMOD_ALT){
623 switch(Event->key.keysym.sym)
624 {
625 case SDLK_RETURN:
626 case SDLK_KP_ENTER:
627 graphics::SwitchMode();
628 break;
629 }
630 return;
631 }else
632 if(Event->key.keysym.mod & KMOD_SHIFT){
633 return;
634 }
635
636 // other special non buffered keys
637 switch(Event->key.keysym.sym)
638 {
639 case SDLK_F1: case SDLK_F2: case SDLK_F3: case SDLK_F4: case SDLK_F5:
640 case SDLK_F6: case SDLK_F7: case SDLK_F8: case SDLK_F9: case SDLK_F10:
641 case SDLK_F11: case SDLK_F12: case SDLK_F13: case SDLK_F14: case SDLK_F15:
642 case SDLK_F16: case SDLK_F17: case SDLK_F18: case SDLK_F19: case SDLK_F20:
643 case SDLK_F21: case SDLK_F22: case SDLK_F23: case SDLK_F24:
644 if(FunctionKeyHandler!=NULL)
645 FunctionKeyHandler(Event->key.keysym.sym);
646 return; //no buffer
647
648 case SDLK_SYSREQ:
649 case SDLK_PRINTSCREEN:
650 if(!ScrshotDirectoryName.IsEmpty())
651 DOUBLE_BUFFER->Save(ScrshotNameHandler());
652 return; //no buffer
653 }
654
655 /////////////////////////////////////////////////////////////////////////////////////////
656 ///////////////////////// MODIFIED KEY BUFFER ///////////////////////////////////////////
657 /////////////////////////////////////////////////////////////////////////////////////////
658 int KeyPressed = 0;
659 switch(Event->key.keysym.sym)
660 {
661 case SDLK_RETURN:
662 case SDLK_KP_ENTER:
663 // ex.: both SDL keys are mixed into KEY_ENTER
664 KeyPressed = KEY_ENTER; //TODO SDL1? old comment tip or deadCode: Event->key.keysym.unicode;
665 break;
666
667 case SDLK_DOWN:
668 case SDLK_KP_2:
669 KeyPressed = KEY_DOWN + 0xE000;
670 break;
671
672 case SDLK_UP:
673 case SDLK_KP_8:
674 KeyPressed = KEY_UP + 0xE000;
675 break;
676
677 case SDLK_RIGHT:
678 case SDLK_KP_6:
679 KeyPressed = KEY_RIGHT + 0xE000;
680 break;
681
682 case SDLK_LEFT:
683 case SDLK_KP_4:
684 KeyPressed = KEY_LEFT + 0xE000;
685 break;
686
687 case SDLK_HOME:
688 case SDLK_KP_7:
689 KeyPressed = KEY_HOME + 0xE000;
690 break;
691
692 case SDLK_END:
693 case SDLK_KP_1:
694 KeyPressed = KEY_END + 0xE000;
695 break;
696 case SDLK_PAGEUP:
697 case SDLK_KP_9:
698 KeyPressed = KEY_PAGE_UP + 0xE000;
699 break;
700
701 case SDLK_KP_3:
702 case SDLK_PAGEDOWN:
703 KeyPressed = KEY_PAGE_DOWN + 0xE000;
704 break;
705
706 case SDLK_DELETE:
707 KeyPressed = KEY_DELETE + 0xE000;
708 break;
709
710 case SDLK_INSERT:
711 KeyPressed = KEY_INSERT + 0xE000;
712 break;
713
714 case SDLK_KP_5:
715 case SDLK_KP_PERIOD:
716 KeyPressed = iRestWaitKey;
717 break;
718
719 #if SDL_MAJOR_VERSION == 2
720 default:
721 KeyPressed = Event->key.keysym.sym;
722 if(!KeyPressed)
723 return;
724 #endif
725
726 //TODO SDL1 still compiles? anyone uses it yet??? the same question about DJGPP...
727 #if SDL_MAJOR_VERSION == 1
728 default:
729 KeyPressed = Event->key.keysym.unicode;
730
731 if(!KeyPressed)
732 return;
733 #endif
734 }
735 AddKeyToBuffer(KeyPressed);
736 }
737
738 /**
739 * buffer of yet non processed commands/textInput
740 */
AddKeyToBuffer(int KeyPressed)741 void globalwindowhandler::AddKeyToBuffer(int KeyPressed)
742 { DBG1(KeyPressed);
743 if(KeyPressed==0)return;
744
745 if( std::find(KeyBuffer.begin(), KeyBuffer.end(), KeyPressed) == KeyBuffer.end() ) //prevent dups TODO because of fast key-repeat OS feature? should be the last key on buffer only then
746 KeyBuffer.push_back(KeyPressed);
747 }
748
ProcessMessage(SDL_Event * Event)749 void globalwindowhandler::ProcessMessage(SDL_Event* Event)
750 {
751 Uint32 type;
752 #if SDL_MAJOR_VERSION == 1
753 type=(Event->active.type);
754 #else
755 type=(Event->type);
756 #endif
757
758 switch(type)
759 {
760
761 #if SDL_MAJOR_VERSION == 1
762 case SDL_VIDEOEXPOSE:
763 graphics::BlitDBToScreen();
764 #else
765 case SDL_WINDOWEVENT:
766 switch(Event->window.event)
767 {
768 case SDL_WINDOWEVENT_SHOWN:
769 case SDL_WINDOWEVENT_RESIZED:
770 case SDL_WINDOWEVENT_RESTORED:
771 graphics::BlitDBToScreen();
772 break;
773 }
774 #endif
775 break;
776
777 case SDL_QUIT:
778 if(!QuitMessageHandler || QuitMessageHandler())
779 exit(0);
780 return;
781
782 case SDL_MOUSEBUTTONUP:
783 if(Event->button.button==1 && Event->button.clicks>0){
784 mc.btn = 1;
785 mc.pos.X=Event->button.x;
786 mc.pos.Y=Event->button.y;
787 }
788 break;
789
790 case SDL_MOUSEWHEEL:
791 mc.wheelY = Event->wheel.y;
792 break;
793
794 #if SDL_MAJOR_VERSION == 2 //BEFORE key up or down
795 case SDL_TEXTINPUT: DBG2(Event->key.keysym.sym,Event->text.text[0]);
796 AddKeyToBuffer(Event->text.text[0]);
797 break;
798 #endif
799
800 case SDL_KEYUP: DBGLN;
801 bLastSDLkeyEventIsKeyUp=true;
802 break;
803
804 case SDL_KEYDOWN: DBGLN;
805 ProcessKeyDownMessage(Event);
806 break;
807 }
808
809 }
810
811 // returns true if shift is being pressed
812 // else false
ShiftIsDown()813 truth globalwindowhandler::ShiftIsDown()
814 {
815 return false;
816 }
817
818 // returns filename to be used for screenshot
ScrshotNameHandler()819 festring globalwindowhandler::ScrshotNameHandler()
820 {
821 static int ScrshotCount = 0;
822
823 festring ScrshotNum;
824 if (ScrshotCount < 10) // prepend 0s so that files are properly sorted in browser (up to 999 at least).
825 ScrshotNum << "00" << ScrshotCount;
826 else if (ScrshotCount < 100)
827 ScrshotNum << "0" << ScrshotCount;
828 else
829 ScrshotNum << ScrshotCount;
830
831 festring ScrshotName;
832 ScrshotName << ScrshotDirectoryName << "Scrshot" << ScrshotNum << ".bmp";
833
834 FILE* Scrshot = fopen(ScrshotName.CStr(), "r");
835
836 if (Scrshot)
837 {
838 // file exists; close file and increment ScrshotCount
839 fclose(Scrshot);
840 ++ScrshotCount;
841 return ScrshotNameHandler();
842 }
843
844 // if file doesn't exist; we can use this filename
845 return ScrshotName;
846 }
847
848 #endif /* USE_SDL */
849