]> icculus.org git repositories - taylor/freespace2.git/blob - src/io/mouse.cpp
added copyright header
[taylor/freespace2.git] / src / io / mouse.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Io/Mouse.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to read the mouse.
16  *
17  * $Log$
18  * Revision 1.5  2002/06/09 04:41:22  relnev
19  * added copyright header
20  *
21  * Revision 1.4  2002/06/02 04:26:34  relnev
22  * warning cleanup
23  *
24  * Revision 1.3  2002/05/29 06:25:13  theoddone33
25  * Keyboard input, mouse tracking now work
26  *
27  * Revision 1.2  2002/05/07 03:16:46  theoddone33
28  * The Great Newline Fix
29  *
30  * Revision 1.1.1.1  2002/05/03 03:28:09  root
31  * Initial import.
32  *
33  * 
34  * 4     7/15/99 9:20a Andsager
35  * FS2_DEMO initial checkin
36  * 
37  * 3     6/02/99 6:18p Dave
38  * Fixed TNT lockup problems! Wheeeee!
39  * 
40  * 2     10/07/98 10:53a Dave
41  * Initial checkin.
42  * 
43  * 1     10/07/98 10:49a Dave
44  * 
45  * 29    6/10/98 2:52p Hoffoss
46  * Made mouse code use DI by default, but fall back on normal code if that
47  * fails.
48  * 
49  * 28    5/24/98 1:35p Hoffoss
50  * Fixed bug where  mouse cursor is always recentering with a
51  * mouse_flush() call in debug version.
52  * 
53  * 27    5/22/98 4:50p Hoffoss
54  * Trying to fix mouse acceleration problem..
55  * 
56  * 26    5/21/98 12:26p Lawrance
57  * Fixed mouse jerk at mission start while in debug build only.
58  * 
59  * 25    5/15/98 2:41p Hoffoss
60  * Made mouse default to off (for flying ship) and fixed some new pilot
61  * init bugs.
62  * 
63  * 24    5/08/98 4:13p Hoffoss
64  * Fixed problem with mouse pointer centering causing lost keypresses.
65  * 
66  * 23    5/07/98 6:58p Hoffoss
67  * Made changes to mouse code to fix a number of problems.
68  * 
69  * 22    5/05/98 8:38p Hoffoss
70  * Added sensitivity adjustment to options menu and made it save to pilot
71  * file.
72  * 
73  * 21    5/05/98 1:03p Hoffoss
74  * Fixed initialization bug.
75  * 
76  * 20    5/01/98 5:45p Hoffoss
77  * Made further improvements to the mouse code.
78  * 
79  * 19    5/01/98 3:35p Hoffoss
80  * Made changes to release version of mouse code.
81  * 
82  * 18    5/01/98 1:14p Hoffoss
83  * Changed mouse usage so directInput is only used for release version.
84  * 
85  * 17    4/30/98 5:40p Hoffoss
86  * Added mouse as a supported control to fly the ship.
87  * 
88  * 16    4/29/98 12:13a Lawrance
89  * Add function to check down count of mouse button without reseting the
90  * internal count.  Added hook to reset demo trailer timer when a button
91  * is pressed.
92  * 
93  * 15    4/02/98 5:26p John
94  * 
95  * 14    1/19/98 6:15p John
96  * Fixed all my Optimized Build compiler warnings
97  * 
98  * 13    12/04/97 3:47p John
99  * Made joystick move mouse cursor
100  * 
101  * 12    11/20/97 5:36p Dave
102  * Hooked in a bunch of main hall changes (including sound). Made it
103  * possible to reposition (rewind/ffwd) 
104  * sound buffer pointers. Fixed animation direction change framerate
105  * problem.
106  * 
107  * 11    5/12/97 11:41a John
108  * Added range checking to mouse position
109  * 
110  * 10    4/22/97 5:55p Lawrance
111  * let mouse.cpp decide if mouse has moved
112  * 
113  * 9     4/22/97 12:29p John
114  * Changed mouse code so that you have to call mouse_init for the mouse
115  * stuff to work.
116  * 
117  * 8     4/22/97 10:56a John
118  * fixed some resource leaks.
119  * 
120  * 7     3/26/97 10:52a Lawrance
121  * mouse always on in menus, disappears in gameplay after 1 second
122  * 
123  * 6     3/11/97 1:37p Lawrance
124  * added mouse_up_count(), changed mouse_mark() to mouse_mark_button() &
125  * mouse_mark_move()
126  * 
127  * 5     12/09/96 1:29p Lawrance
128  * adding 3 button support
129  * 
130  * 4     12/03/96 4:19p John
131  * Added some code so that holding down the mouse buttons between menus
132  * doesn't select the next menu.
133  *
134  * $NoKeywords: $
135  */
136
137 #ifndef PLAT_UNIX
138 #include <windows.h>
139 #include <windowsx.h>
140 #endif
141
142 #include "mouse.h"
143 #include "2d.h"
144 #include "osapi.h"
145
146 #define MOUSE_MODE_DI   0
147 #define MOUSE_MODE_WIN  1
148
149 #ifdef NDEBUG
150 LOCAL int Mouse_mode = MOUSE_MODE_DI;
151 #else
152 LOCAL int Mouse_mode = MOUSE_MODE_WIN;
153 #endif
154
155 LOCAL int mouse_inited = 0;
156 LOCAL int Di_mouse_inited = 0;
157 LOCAL int Mouse_x;
158 LOCAL int Mouse_y;
159
160 CRITICAL_SECTION mouse_lock;
161
162 // #define USE_DIRECTINPUT
163
164 int mouse_flags;
165 int mouse_left_pressed = 0;
166 int mouse_right_pressed = 0;
167 int mouse_middle_pressed = 0;
168 int mouse_left_up = 0;
169 int mouse_right_up = 0;
170 int mouse_middle_up = 0;
171 int Mouse_dx = 0;
172 int Mouse_dy = 0;
173 int Mouse_dz = 0;
174
175 int Mouse_sensitivity = 4;
176 int Use_mouse_to_fly = 0;
177 int Mouse_hidden = 0;
178 int Keep_mouse_centered = 0;;
179
180 int di_init();
181 void di_cleanup();
182 void mouse_force_pos(int x, int y);
183 void mouse_eval_deltas_di();
184
185 int mouse_is_visible()
186 {
187         return !Mouse_hidden;
188 }
189
190 void mouse_close()
191 {
192         if (!mouse_inited)
193                 return;
194
195 #ifdef USE_DIRECTINPUT
196         di_cleanup();
197 #endif
198         mouse_inited = 0;
199 #ifdef PLAT_UNIX
200         STUB_FUNCTION;
201 #else
202         DeleteCriticalSection( &mouse_lock );
203 #endif
204 }
205
206 void mouse_init()
207 {
208         // Initialize queue
209         if ( mouse_inited ) return;
210         mouse_inited = 1;
211
212 #ifdef PLAT_UNIX
213         STUB_FUNCTION;
214 #else
215         InitializeCriticalSection( &mouse_lock );
216 #endif
217
218         ENTER_CRITICAL_SECTION(&mouse_lock);
219
220         mouse_flags = 0;
221         Mouse_x = gr_screen.max_w / 2;
222         Mouse_y = gr_screen.max_h / 2;
223
224 #ifdef USE_DIRECTINPUT
225         if (!di_init())
226                 Mouse_mode = MOUSE_MODE_WIN;
227 #else
228         Mouse_mode = MOUSE_MODE_WIN;
229 #endif
230
231         LEAVE_CRITICAL_SECTION(&mouse_lock);    
232
233         atexit( mouse_close );
234 }
235
236
237 // ----------------------------------------------------------------------------
238 // mouse_mark_button() is called asynchronously by the OS when a mouse button
239 // goes up or down.  The mouse button that is affected is passed via the 
240 // flags parameter.  
241 //
242 // parameters:   flags ==> mouse button pressed/released
243 //               set   ==> 1 - button is pressed
244 //                         0 - button is released
245
246 void mouse_mark_button( uint flags, int set)
247 {
248         if ( !mouse_inited ) return;
249
250         ENTER_CRITICAL_SECTION(&mouse_lock);
251
252         if ( !(mouse_flags & MOUSE_LEFT_BUTTON) )       {
253
254                 if ( (flags & MOUSE_LEFT_BUTTON) && (set == 1) ) {
255                         mouse_left_pressed++;
256
257 ////////////////////////////
258 /// SOMETHING TERRIBLE IS ABOUT TO HAPPEN.  I FEEL THIS IS NECESSARY FOR THE DEMO, SINCE
259 /// I DON'T WANT TO CALL CRITICAL SECTION CODE EACH FRAME TO CHECK THE LEFT MOUSE BUTTON.
260 /// PLEASE SEE ALAN FOR MORE INFORMATION.
261 ////////////////////////////
262 #ifdef FS2_DEMO
263                                         {
264                                         extern void demo_reset_trailer_timer();
265                                         demo_reset_trailer_timer();
266                                         }
267 #endif
268 ////////////////////////////
269 /// IT'S OVER.  SEE, IT WASN'T SO BAD RIGHT?  IT'S IS VERY UGLY LOOKING, I KNOW.
270 ////////////////////////////
271
272                 }
273         }
274         else {
275                 if ( (flags & MOUSE_LEFT_BUTTON) && (set == 0) ){
276                         mouse_left_up++;
277                 }
278         }
279
280         if ( !(mouse_flags & MOUSE_RIGHT_BUTTON) )      {
281
282                 if ( (flags & MOUSE_RIGHT_BUTTON) && (set == 1) ){
283                         mouse_right_pressed++;
284                 }
285         }
286         else {
287                 if ( (flags & MOUSE_RIGHT_BUTTON) && (set == 0) ){
288                         mouse_right_up++;
289                 }
290         }
291
292         if ( !(mouse_flags & MOUSE_MIDDLE_BUTTON) )     {
293
294                 if ( (flags & MOUSE_MIDDLE_BUTTON) && (set == 1) ){
295                         mouse_middle_pressed++;
296                 }
297         }
298         else {
299                 if ( (flags & MOUSE_MIDDLE_BUTTON) && (set == 0) ){
300                         mouse_middle_up++;
301                 }
302         }
303
304         if ( set ){
305                 mouse_flags |= flags;
306         } else {
307                 mouse_flags &= ~flags;
308         }
309
310         LEAVE_CRITICAL_SECTION(&mouse_lock);    
311 }
312
313 void mouse_flush()
314 {
315         if (!mouse_inited)
316                 return;
317
318         mouse_eval_deltas();
319         Mouse_dx = Mouse_dy = Mouse_dz = 0;
320         ENTER_CRITICAL_SECTION(&mouse_lock);
321         mouse_left_pressed = 0;
322         mouse_right_pressed = 0;
323         mouse_middle_pressed = 0;
324         mouse_flags = 0;
325         LEAVE_CRITICAL_SECTION(&mouse_lock);    
326 }
327
328 int mouse_down_count(int n, int reset_count)
329 {
330         int tmp = 0;
331         if ( !mouse_inited ) return 0;
332
333         if ( (n < LOWEST_MOUSE_BUTTON) || (n > HIGHEST_MOUSE_BUTTON)) return 0;
334
335         ENTER_CRITICAL_SECTION(&mouse_lock);
336
337         switch (n) {
338                 case MOUSE_LEFT_BUTTON:
339                         tmp = mouse_left_pressed;
340                         if ( reset_count ) {
341                                 mouse_left_pressed = 0;
342                         }
343                         break;
344
345                 case MOUSE_RIGHT_BUTTON:
346                         tmp = mouse_right_pressed;
347                         if ( reset_count ) {
348                                 mouse_right_pressed = 0;
349                         }
350                         break;
351
352                 case MOUSE_MIDDLE_BUTTON:
353                         tmp = mouse_middle_pressed;
354                         if ( reset_count ) {
355                                 mouse_middle_pressed = 0;
356                         }
357                         break;
358         } // end switch
359
360         LEAVE_CRITICAL_SECTION(&mouse_lock);    
361
362         return tmp;
363 }
364
365 // mouse_up_count() returns the number of times button n has gone from down to up
366 // since the last call
367 //
368 // parameters:  n - button of mouse (see #define's in mouse.h)
369 //
370 int mouse_up_count(int n)
371 {
372         int tmp = 0;
373         if ( !mouse_inited ) return 0;
374
375         if ( (n < LOWEST_MOUSE_BUTTON) || (n > HIGHEST_MOUSE_BUTTON)) return 0;
376
377         ENTER_CRITICAL_SECTION(&mouse_lock);
378
379         switch (n) {
380                 case MOUSE_LEFT_BUTTON:
381                         tmp = mouse_left_up;
382                         mouse_left_up = 0;
383                         break;
384
385                 case MOUSE_RIGHT_BUTTON:
386                         tmp = mouse_right_up;
387                         mouse_right_up = 0;
388                         break;
389
390                 case MOUSE_MIDDLE_BUTTON:
391                         tmp = mouse_middle_up;
392                         mouse_middle_up = 0;
393                         break;
394
395                 default:
396                         Assert(0);      // can't happen
397                         break;
398         } // end switch
399
400         LEAVE_CRITICAL_SECTION(&mouse_lock);    
401
402         return tmp;
403 }
404
405 // returns 1 if mouse button btn is down, 0 otherwise
406
407 int mouse_down(int btn)
408 {
409         int tmp;
410         if ( !mouse_inited ) return 0;
411
412         if ( (btn < LOWEST_MOUSE_BUTTON) || (btn > HIGHEST_MOUSE_BUTTON)) return 0;
413
414
415         ENTER_CRITICAL_SECTION(&mouse_lock);
416
417
418         if ( mouse_flags & btn )
419                 tmp = 1;
420         else
421                 tmp = 0;
422
423         LEAVE_CRITICAL_SECTION(&mouse_lock);    
424
425         return tmp;
426 }
427
428 // returns the fraction of time btn has been down since last call 
429 // (currently returns 1 if buttons is down, 0 otherwise)
430 //
431 float mouse_down_time(int btn)
432 {
433         float tmp;
434         if ( !mouse_inited ) return 0.0f;
435
436         if ( (btn < LOWEST_MOUSE_BUTTON) || (btn > HIGHEST_MOUSE_BUTTON)) return 0.0f;
437
438         ENTER_CRITICAL_SECTION(&mouse_lock);
439
440         if ( mouse_flags & btn )
441                 tmp = 1.0f;
442         else
443                 tmp = 0.0f;
444
445         LEAVE_CRITICAL_SECTION(&mouse_lock);
446
447         return tmp;
448 }
449
450 void mouse_get_delta(int *dx, int *dy, int *dz)
451 {
452         if (dx)
453                 *dx = Mouse_dx;
454         if (dy)
455                 *dy = Mouse_dy;
456         if (dz)
457                 *dz = Mouse_dz;
458 }
459
460 // Forces the actual windows cursor to be at (x,y).  This may be independent of our tracked (x,y) mouse pos.
461 void mouse_force_pos(int x, int y)
462 {
463         if (os_foreground()) {  // only mess with windows's mouse if we are in control of it
464 #ifdef PLAT_UNIX
465                 SDL_WarpMouse(x, y);
466 #else
467                 POINT pnt;
468
469                 pnt.x = x;
470                 pnt.y = y;
471                 ClientToScreen((HWND) os_get_window(), &pnt);
472                 SetCursorPos(pnt.x, pnt.y);
473 #endif
474         }
475 }
476
477 #include "gamesequence.h"
478
479 // change in mouse position since last call
480 void mouse_eval_deltas()
481 {
482         static int old_x = 0;
483         static int old_y = 0;
484         int tmp_x, tmp_y, cx, cy;
485
486         Mouse_dx = Mouse_dy = Mouse_dz = 0;
487         if (!mouse_inited)
488                 return;
489
490         if (Mouse_mode == MOUSE_MODE_DI) {
491                 mouse_eval_deltas_di();
492                 return;
493         }
494
495         cx = gr_screen.max_w / 2;
496         cy = gr_screen.max_h / 2;
497
498         ENTER_CRITICAL_SECTION(&mouse_lock);
499
500 #ifdef PLAT_UNIX
501         SDL_GetMouseState (&tmp_x, &tmp_y);
502 #else
503         POINT pnt;
504         GetCursorPos(&pnt);
505         ScreenToClient((HWND)os_get_window(), &pnt);
506         tmp_x = pnt.x;
507         tmp_y = pnt.y;
508 #endif
509
510         Mouse_dx = tmp_x - old_x;
511         Mouse_dy = tmp_y - old_y;
512         Mouse_dz = 0;
513
514         if (Keep_mouse_centered && Mouse_hidden) {
515                 if (Mouse_dx || Mouse_dy)
516                         mouse_force_pos(cx, cy);
517
518                 old_x = cx;
519                 old_y = cy;
520
521         } else {
522                 old_x = tmp_x;
523                 old_y = tmp_y;
524         }
525
526         LEAVE_CRITICAL_SECTION(&mouse_lock);
527 }
528
529 #ifndef PLAT_UNIX
530 #include "vdinput.h"
531
532 static LPDIRECTINPUT                    Di_mouse_obj = NULL;
533 static LPDIRECTINPUTDEVICE      Di_mouse = NULL;
534 #endif
535
536 void mouse_eval_deltas_di()
537 {
538 #ifdef PLAT_UNIX
539         STUB_FUNCTION;
540 #else
541         int repeat = 1;
542         HRESULT hr = 0;
543         DIMOUSESTATE mouse_state;
544
545         Mouse_dx = Mouse_dy = Mouse_dz = 0;
546         if (!Di_mouse_inited)
547                 return;
548
549         repeat = 1;
550         memset(&mouse_state, 0, sizeof(mouse_state));
551         while (repeat) {
552                 repeat = 0;
553
554                 hr = Di_mouse->GetDeviceState(sizeof(mouse_state), &mouse_state);
555                 if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED)) {
556                         // DirectInput is telling us that the input stream has
557                         // been interrupted.  We aren't tracking any state
558                         // between polls, so we don't have any special reset
559                         // that needs to be done.  We just re-acquire and
560                         // try again.
561                         Sleep(500);             // Pause a half second...
562                         hr = Di_mouse->Acquire();
563                         if (SUCCEEDED(hr))
564                                 repeat = 1;
565                 }
566         }
567
568         if (SUCCEEDED(hr)) {
569                 Mouse_dx = (int) mouse_state.lX;
570                 Mouse_dy = (int) mouse_state.lY;
571                 Mouse_dz = (int) mouse_state.lZ;
572
573         } else {
574                 Mouse_dx = Mouse_dy = Mouse_dz = 0;
575         }
576
577         Mouse_x += Mouse_dx;
578         Mouse_y += Mouse_dy;
579
580         if (Mouse_x < 0)
581                 Mouse_x = 0;
582
583         if (Mouse_y < 0)
584                 Mouse_y = 0;
585
586         if (Mouse_x >= gr_screen.max_w)
587                 Mouse_x = gr_screen.max_w - 1;
588
589         if (Mouse_y >= gr_screen.max_h)
590                 Mouse_y = gr_screen.max_h - 1;
591
592         // keep the mouse inside our window so we don't switch applications or anything (debug bug people reported?)
593         // JH: Dang!  This makes the mouse readings in DirectInput act screwy!
594 //      mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
595 #endif
596 }
597
598 int mouse_get_pos(int *xpos, int *ypos)
599 {
600         int flags;
601
602         if (Mouse_mode == MOUSE_MODE_DI) {
603                 if (xpos)
604                         *xpos = Mouse_x;
605
606                 if (ypos)
607                         *ypos = Mouse_y;
608
609                 return mouse_flags;
610         }
611
612         if (!mouse_inited) {
613                 *xpos = *ypos = 0;
614                 return 0;
615         }
616
617 #ifdef PLAT_UNIX
618         flags = SDL_GetMouseState (&Mouse_x, &Mouse_y);
619         // DDOI - FIXME?
620 #else
621         POINT pnt;
622         GetCursorPos(&pnt);
623         ScreenToClient((HWND)os_get_window(), &pnt);
624
625 //      EnterCriticalSection(&mouse_lock);
626
627         flags = mouse_flags;
628         Mouse_x = pnt.x;
629         Mouse_y = pnt.y;
630 #endif
631
632 //      LeaveCriticalSection(&mouse_lock);
633
634         if (Mouse_x < 0){
635                 Mouse_x = 0;
636         }
637
638         if (Mouse_y < 0){
639                 Mouse_y = 0;
640         }
641
642         if (Mouse_x >= gr_screen.max_w){
643                 Mouse_x = gr_screen.max_w - 1;
644         }
645
646         if (Mouse_y >= gr_screen.max_h){
647                 Mouse_y = gr_screen.max_h - 1;
648         }
649         
650         if (xpos){
651                 *xpos = Mouse_x;
652         }
653
654         if (ypos){
655                 *ypos = Mouse_y;
656         }
657
658         return flags;
659 }
660
661 void mouse_get_real_pos(int *mx, int *my)
662 {
663         if (Mouse_mode == MOUSE_MODE_DI) {
664                 *mx = Mouse_x;
665                 *my = Mouse_y;
666                 return;
667         }
668
669 #ifdef PLAT_UNIX
670         SDL_GetMouseState (mx, my);
671 #else
672         POINT pnt;
673         GetCursorPos(&pnt);
674         ScreenToClient((HWND)os_get_window(), &pnt);
675         
676         *mx = pnt.x;
677         *my = pnt.y;
678 #endif
679 }
680
681 void mouse_set_pos(int xpos, int ypos)
682 {
683         if (Mouse_mode == MOUSE_MODE_DI) {
684                 Mouse_x = xpos;
685                 Mouse_y = ypos;
686                 return;
687         }
688
689         if ((xpos != Mouse_x) || (ypos != Mouse_y)){
690                 mouse_force_pos(xpos, ypos);
691         }
692 }
693
694 int di_init()
695 {
696 #ifdef PLAT_UNIX
697         STUB_FUNCTION;
698         return 0;
699 #else
700         HRESULT hr;
701
702         if (Mouse_mode == MOUSE_MODE_WIN){
703                 return 0;
704         }
705
706         Di_mouse_inited = 0;
707         hr = DirectInputCreate(GetModuleHandle(NULL), DIRECTINPUT_VERSION, &Di_mouse_obj, NULL);
708         if (FAILED(hr)) {
709                 hr = DirectInputCreate(GetModuleHandle(NULL), 0x300, &Di_mouse_obj, NULL);
710                 if (FAILED(hr)) {
711                         mprintf(( "DirectInputCreate() failed!\n" ));
712                         return FALSE;
713                 }
714         }
715
716         hr = Di_mouse_obj->CreateDevice(GUID_SysMouse, &Di_mouse, NULL);
717         if (FAILED(hr)) {
718                 mprintf(( "CreateDevice() failed!\n" ));
719                 return FALSE;
720         }
721
722         hr = Di_mouse->SetDataFormat(&c_dfDIMouse);
723         if (FAILED(hr)) {
724                 mprintf(( "SetDataFormat() failed!\n" ));
725                 return FALSE;
726         }
727
728         hr = Di_mouse->SetCooperativeLevel((HWND)os_get_window(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
729         if (FAILED(hr)) {
730                 mprintf(( "SetCooperativeLevel() failed!\n" ));
731                 return FALSE;
732         }
733 /*
734         DIPROPDWORD hdr;
735
736         // Turn on buffering
737         hdr.diph.dwSize = sizeof(DIPROPDWORD); 
738         hdr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
739         hdr.diph.dwObj = 0;             
740         hdr.diph.dwHow = DIPH_DEVICE;   // Apply to entire device
741         hdr.dwData = 16;        //MAX_BUFFERED_KEYBOARD_EVENTS;
742
743         hr = Di_mouse->SetProperty( DIPROP_BUFFERSIZE, &hdr.diph );
744         if (FAILED(hr)) {
745                 mprintf(( "SetProperty DIPROP_BUFFERSIZE failed\n" ));
746                 return FALSE;
747         }
748
749         Di_event = CreateEvent( NULL, FALSE, FALSE, NULL );
750         Assert(Di_event != NULL);
751
752         hr = Di_mouse->SetEventNotification(Di_event);
753         if (FAILED(hr)) {
754                 mprintf(( "SetEventNotification failed\n" ));
755                 return FALSE;
756         }
757 */
758         Di_mouse->Acquire();
759
760         Di_mouse_inited = 1;
761         return TRUE;
762 #endif
763 }
764
765 void di_cleanup()
766 {
767 #ifdef PLAT_UNIX
768         STUB_FUNCTION;
769 #else
770         // Destroy any lingering IDirectInputDevice object.
771         if (Di_mouse) {
772                 // Unacquire the device one last time just in case we got really confused
773                 // and tried to exit while the device is still acquired.
774                 Di_mouse->Unacquire();
775
776                 Di_mouse->Release();
777                 Di_mouse = NULL;
778         }
779
780         // Destroy any lingering IDirectInput object.
781         if (Di_mouse_obj) {
782                 Di_mouse_obj->Release();
783                 Di_mouse_obj = NULL;
784         }
785
786         Di_mouse_inited = 0;
787 #endif
788 }
789