include/*.bat, include/test.*: remove unnecessary files
[btb/d2x.git] / arch / win32 / mouse.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 /*
14 * $Source: /cvs/cvsroot/d2x/arch/win32/mouse.c,v $
15 * $Revision: 1.1.1.1 $
16 * $Author: bradleyb $
17 * $Date: 2001-01-19 03:30:15 $
18
19 * Functions to access Mouse and Cyberman...
20
21 * $Log: not supported by cvs2svn $
22 * Revision 1.5  1999/10/15 05:27:48  donut
23 * include to fix undef'd err
24 *
25 * Revision 1.4  1999/10/14 03:08:10  donut
26 * changed exit to mprintf on unknown mouse event
27 *
28 * Revision 1.3  1999/10/09 05:03:57  donut
29 * fixed win32 exit on mouse move
30 *
31 * Revision 1.2  1999/09/05 04:19:19  sekmu
32 * made mouse exclusive for windows
33 *
34 * Revision 1.1.1.1  1999/06/14 22:00:37  donut
35 * Import of d1x 1.37 source.
36 *
37 * Revision 1.8  1996/02/21  13:57:36  allender
38 * cursor device manager stuff added here so as not to
39 * rely on InterfaceLib anymore
40 *
41 * Revision 1.7  1995/10/17  15:42:21  allender
42 * new mouse function to determine single button press
43 *
44 * Revision 1.6  1995/10/03  11:27:31  allender
45 * fixed up hotspot problems with the mouse on multiple monitors
46 *
47 * Revision 1.5  1995/07/13  11:27:08  allender
48 * trap button checks at MAX_MOUSE_BUTTONS
49 *
50 * Revision 1.4  1995/06/25  21:56:53  allender
51 * added events include
52 *
53 * Revision 1.3  1995/05/11  17:06:38  allender
54 * fixed up mouse routines
55 *
56 * Revision 1.2  1995/05/11  13:05:53  allender
57 * of mouse handler code
58 *
59 * Revision 1.1  1995/05/05  09:54:45  allender
60 * Initial revision
61 *
62 * Revision 1.9  1995/01/14  19:19:52  john
63 * Fixed signed short error cmp with -1 that caused mouse
64 * to break under Watcom 10.0
65
66 * Revision 1.8  1994/12/27  12:38:23  john
67 * Made mouse use temporary dos buffer instead of
68
69 * allocating its own.
70
71
72 * Revision 1.7  1994/12/05  23:54:53  john
73 * Fixed bug with mouse_get_delta only returning positive numbers..
74
75 * Revision 1.6  1994/11/18  23:18:18  john
76 * Changed some shorts to ints.
77
78 * Revision 1.5  1994/09/13  12:34:02  john
79 * Added functions to get down count and state.
80
81 * Revision 1.4  1994/08/29  20:52:19  john
82 * Added better cyberman support; also, joystick calibration
83 * value return funcctiionn,
84
85 * Revision 1.3  1994/08/24  18:54:32  john
86 * *** empty log message ***
87
88 * Revision 1.2  1994/08/24  18:53:46  john
89 * Made Cyberman read like normal mouse; added dpmi module; moved
90 * mouse from assembly to c. Made mouse buttons return time_down.
91
92 * Revision 1.1  1994/08/24  13:56:37  john
93 * Initial revision
94
95
96 */
97
98 #define WIN32_LEAN_AND_MEAN
99 #include <dinput.h>
100
101
102 #include <stdlib.h>
103 #include <stdio.h>
104 #include <string.h>
105
106 #include "error.h"
107 #include "fix.h"
108 #include "mouse.h"
109 #include "mono.h"
110 #include "timer.h"
111
112 // These are to kludge up a bit my slightly broken GCC directx port.
113 #ifndef E_FAIL
114 #define E_FAIL (HRESULT)0x80004005L
115 #endif
116 #ifndef SUCCEEDED
117 #define SUCCEEDED(a) ((HRESULT)(a) >= 0)
118 #endif
119 #ifndef S_OK
120 #define S_OK 0
121 #define S_FALSE 1
122 #endif
123 #ifndef SEVERITY_SUCCESS
124 #define SEVERITY_SUCCESS    0
125 #define SEVERITY_ERROR      1
126 #endif
127 #ifndef FACILITY_WIN32
128 #define FACILITY_WIN32                   7
129 #endif
130 #ifndef FIELD_OFFSET
131 #define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
132 #endif
133
134 #define ME_CURSOR_MOVED (1<<0)
135 #define ME_LB_P                 (1<<1)
136 #define ME_LB_R                 (1<<2)
137 #define ME_RB_P                 (1<<3)
138 #define ME_RB_R                 (1<<4)
139 #define ME_MB_P                 (1<<5)
140 #define ME_MB_R                 (1<<6)
141 #define ME_OB_P                 (1<<7)
142 #define ME_OB_R                 (1<<8)
143 #define ME_X_C                  (1<<9)
144 #define ME_Y_C                  (1<<10)
145 #define ME_Z_C                  (1<<11)
146 #define ME_P_C                  (1<<12)
147 #define ME_B_C                  (1<<13)
148 #define ME_H_C                  (1<<14)
149 #define ME_O_C                  (1<<15)
150
151 typedef struct event_info {
152         short x;
153         short y;
154         short z;
155         short pitch;
156         short bank;
157         short heading;
158         ushort button_status;
159         ushort device_dependant;
160 } event_info;
161
162 typedef struct mouse_info {
163         fix             ctime;
164         ubyte   cyberman;
165         int             num_buttons;
166         ubyte   pressed[MOUSE_MAX_BUTTONS];
167         fix             time_went_down[MOUSE_MAX_BUTTONS];
168         fix             time_held_down[MOUSE_MAX_BUTTONS];
169         uint    num_downs[MOUSE_MAX_BUTTONS];
170         uint    num_ups[MOUSE_MAX_BUTTONS];
171         //      ubyte   went_down; /* Not in PC version, not needed with 'num_downs' etc */
172         event_info *x_info;
173         ushort  button_status;
174 } mouse_info;
175
176 typedef struct cyberman_info {
177         ubyte device_type;
178         ubyte major_version;
179         ubyte minor_version;
180         ubyte x_descriptor;
181         ubyte y_descriptor;
182         ubyte z_descriptor;
183         ubyte pitch_descriptor;
184         ubyte roll_descriptor;
185         ubyte yaw_descriptor;
186         ubyte reserved;
187 } cyberman_info;
188
189 static mouse_info Mouse;
190
191 static int Mouse_installed = 0;
192
193 int WMMouse_Handler_Ready = 0;
194 int mouse_wparam, mouse_lparam, mouse_msg;
195
196
197 //GGI data:
198 //extern  ggi_visual_t          visual;
199 //extern  ggi_directbuffer_t            dbuf;   // GGI direct acces to screen memory
200 //extern  ggi_pixellinearbuffer *plb;
201
202 //Mouse globals
203 static double mouse_x, mouse_y;
204 static double mouse_saved_x, mouse_saved_y; //used when hiding/unhiding to reset the real (displayed) postion
205 double mouse_accel=1.0;
206
207 void DrawMouse(void);
208 void EraseMouse(void);
209 void MoveMouse(/*int button,*/ int x, int y);
210
211 #define WIN_WIDTH 640
212 #define WIN_HEIGHT 480
213 #define SCR_WIDTH 640
214 #define SCR_HEIGHT 480
215
216 LPDIRECTINPUT g_lpdi;
217 LPDIRECTINPUTDEVICE g_lpdidMouse;
218 extern HWND g_hWnd;
219
220
221 HRESULT ReadMouse (DIDEVICEOBJECTDATA *pdidod)
222 {
223         ULONG cElements = 1;
224         HRESULT hr;
225
226         if (g_lpdidMouse == NULL)
227                 return E_FAIL;
228
229         hr = IDirectInputDevice_GetDeviceData (
230                 g_lpdidMouse,
231                 sizeof (*pdidod),
232                 pdidod,
233                 (int *) &cElements,
234                 0);
235
236         if (hr == DIERR_INPUTLOST)
237         {
238                 hr = IDirectInputDevice_Acquire (g_lpdidMouse);
239                 if (SUCCEEDED (hr))
240                 {
241                         hr = IDirectInputDevice_GetDeviceData (
242                                 g_lpdidMouse,
243                                 sizeof (*pdidod),
244                                 pdidod,
245                                 (int *) &cElements,
246                                 0);
247                 }
248         }
249
250         if (SUCCEEDED (hr) && cElements != 1)
251                 hr = E_FAIL;
252
253         return hr;
254 }
255
256
257 void UpdateMouseState (DIDEVICEOBJECTDATA *pdidod)
258 {
259 //        fix timeNow = timer_get_fixed_seconds ();
260
261         ULONG iEvt = pdidod->dwOfs;
262         switch (iEvt)
263         {
264                 case DIMOFS_BUTTON0:
265                 case DIMOFS_BUTTON1:
266                 case DIMOFS_BUTTON2:
267                 case DIMOFS_BUTTON3:
268                 {
269                         BOOL bPressed = pdidod->dwData & 0x80;
270                         ULONG iButton = (iEvt - DIMOFS_BUTTON0) + MB_LEFT;
271                         if (bPressed)
272                         {
273                                 if (!Mouse.pressed [iButton])
274                                 {
275                                         Mouse.pressed [iButton] = 1;
276                                         Mouse.time_went_down [iButton] = Mouse.ctime;
277                                         Mouse.num_downs [iButton]++;
278                                         //                      Mouse.went_down = 1;
279                                 }
280                                 Mouse.num_downs [iButton] ++;
281                         }
282                         else
283                         {
284                                 if (Mouse.pressed [iButton])
285                                 {
286                                         Mouse.pressed [iButton] = 0;
287                                         Mouse.time_held_down [iButton] += Mouse.ctime - Mouse.time_went_down [iButton];
288                                         Mouse.num_ups [iButton]++;
289                                         //                      Mouse.went_down = 0;
290                                 }
291                         }
292                         break;
293                 }
294                 case DIMOFS_X:
295                         mouse_x += (double) ((LONG) pdidod->dwData);
296                         break;
297
298                 case DIMOFS_Y:
299                         mouse_y += (double) ((LONG) pdidod->dwData);
300                         break;
301                 case DIMOFS_Z:
302                         break;//hm, handle this?
303                 default:
304                         mprintf((0,"unknown mouse event %i\n",iEvt));
305 //                      exit (iEvt);//not happy.
306                         break;
307         }
308 }
309
310 void mouse_handler()
311 {
312         DIDEVICEOBJECTDATA didod;
313
314         Mouse.ctime = timer_get_fixed_seconds();
315
316         while (SUCCEEDED (ReadMouse (&didod)))
317         {
318                 UpdateMouseState (&didod);
319         }
320 }
321
322 void mouse_flush()
323 {
324         int i;
325         fix CurTime;
326         
327         if (!Mouse_installed)
328                 return;
329
330         mouse_handler();
331         //      _disable();
332         CurTime = timer_get_fixed_seconds();
333         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
334                 Mouse.pressed[i] = 0;
335                 Mouse.time_went_down[i] = CurTime;
336                 Mouse.time_held_down[i] = 0;
337                 Mouse.num_downs[i] = 0;
338                 Mouse.num_ups[i] = 0;
339         }
340         //      Mouse.went_down = 0; /* mac only */
341         //      _enable();
342
343         {
344                 ULONG cElements = INFINITE;
345 //                HRESULT hr =
346         IDirectInputDevice_GetDeviceData (
347                         g_lpdidMouse,
348                         sizeof (DIDEVICEOBJECTDATA),
349                         NULL,
350                         (int *) &cElements,
351                         0);
352         }
353 }
354
355
356 void mouse_close(void)
357 {
358         //      if (Mouse_installed)   // DPH: Unnecessary...
359         WMMouse_Handler_Ready=Mouse_installed = 0;
360
361         if (g_lpdidMouse != NULL)
362         {
363                 IDirectInputDevice_Unacquire (g_lpdidMouse);
364                 IDirectInputDevice_Release (g_lpdidMouse);
365                 g_lpdidMouse = NULL;
366         }
367         if (g_lpdi != NULL)
368         {
369                 IDirectInput_Release (g_lpdi);
370                 g_lpdi = NULL;
371         }
372 }
373
374
375
376 int mouse_init(int unused)
377 {
378         if (Mouse_installed)
379                 return Mouse.num_buttons;
380         
381         {
382                 HRESULT hr;
383
384                 if (SUCCEEDED (hr = DirectInputCreate (GetModuleHandle (NULL), DIRECTINPUT_VERSION, &g_lpdi, NULL)))
385                 {
386                         if (SUCCEEDED (hr = IDirectInput_CreateDevice (g_lpdi,(void *) &GUID_SysMouse, &g_lpdidMouse, NULL)))
387                         {
388                                 DIPROPDWORD dipdw;
389                                 dipdw.diph.dwSize = sizeof (DIPROPDWORD);
390                                 dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER);
391                                 dipdw.diph.dwObj = 0;
392                                 dipdw.diph.dwHow = DIPH_DEVICE;
393                                 dipdw.dwData = 40;
394
395                                 if (SUCCEEDED (hr = IDirectInputDevice_SetDataFormat (g_lpdidMouse, &c_dfDIMouse)) &&
396                                         //changed on 9/4/99 by Victor Rachels NONEX -> Exclusive
397                                         SUCCEEDED (hr = IDirectInputDevice_SetCooperativeLevel (g_lpdidMouse, g_hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)) &&
398                                         //end this section edit -VR
399                                         SUCCEEDED (hr = IDirectInputDevice_SetProperty (g_lpdidMouse, DIPROP_BUFFERSIZE, &dipdw.diph)) &&
400                                         SUCCEEDED (hr = IDirectInputDevice_Acquire (g_lpdidMouse)))
401                                 {
402                                 }
403                                 else
404                                 {
405                                         IDirectInputDevice_Release (g_lpdidMouse);
406                                         g_lpdidMouse = NULL;
407                                         return 0;
408                                 }
409                         }
410                 }
411         }
412         Mouse.num_buttons = 3;
413         
414         WMMouse_Handler_Ready=Mouse_installed = 1;
415         atexit(mouse_close);
416         mouse_flush();
417         //      mouse_set_center();
418         
419         return Mouse.num_buttons;
420 }
421
422 //WHS: added this
423 void mouse_center() {
424         mouse_x=mouse_saved_x=WIN_WIDTH/2;
425         mouse_y=mouse_saved_y=WIN_HEIGHT/2;
426 }
427
428 void mouse_get_pos( int *x, int *y)
429 {
430         mouse_handler(); //temp
431         
432         *x=(int) mouse_x;
433         *y=(int) mouse_y;
434 }
435
436 void mouse_get_delta( int *dx, int *dy )
437 {
438         if (!Mouse_installed) {
439                 *dx = *dy = 0;
440                 return;
441         }
442         mouse_handler(); //temp
443         
444         *dx = (int) mouse_x - WIN_WIDTH/2;
445         *dy = (int) mouse_y - WIN_HEIGHT/2;
446         
447         //Now reset the mouse position to the center of the screen
448         mouse_x = (double) WIN_WIDTH/2;
449         mouse_y = (double) WIN_HEIGHT/2;
450 }
451
452 void mouse_get_delta_no_reset( int *dx, int *dy )
453 {
454         if (!Mouse_installed) {
455                 *dx = *dy = 0;
456                 return;
457         }
458         mouse_handler(); //temp
459         
460         *dx = (int) mouse_x - WIN_WIDTH/2;
461         *dy = (int) mouse_y - WIN_HEIGHT/2;
462 }
463
464 int mouse_get_btns()
465 {
466         int  i;
467         uint flag=1;
468         int  status = 0;
469         
470         if (!Mouse_installed)
471                 return 0;
472
473         mouse_handler(); //temp
474         
475         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
476                 if (Mouse.pressed[i])
477                         status |= flag;
478                 flag <<= 1;
479         }
480         return status;
481 }
482
483 /* This should be replaced with mouse_button_down_count(int button)     */
484 int mouse_went_down(int button)
485 {
486         int count;
487         
488         if (!Mouse_installed)
489                 return 0;
490
491         mouse_handler(); //temp
492         
493         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
494                 return 0;
495         
496         //      _disable();             
497         count = Mouse.num_downs[button];
498         Mouse.num_downs[button] = 0;
499         
500         //      _enable();
501         return count;
502 }
503
504 // Returns how many times this button has went down since last call.
505 int mouse_button_down_count(int button) 
506 {
507         int count;
508         
509         if (!Mouse_installed)
510                 return 0;
511         
512         mouse_handler(); //temp
513         
514         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
515                 return 0;
516         
517         //      _disable();
518         count = Mouse.num_downs[button];
519         Mouse.num_downs[button] = 0;
520         //      _enable();
521         return count;
522 }
523
524 // Returns 1 if this button is currently down
525 int mouse_button_state(int button)
526 {
527         int state;
528         
529         if (!Mouse_installed)
530                 return 0;
531         
532         mouse_handler(); //temp
533         
534         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
535                 return 0;
536         
537         //      _disable();
538         state = Mouse.pressed[button];
539         //      _enable();
540         return state;
541 }
542
543 // Returns how long this button has been down since last call.
544 fix mouse_button_down_time(int button)  
545 {
546         fix time_down, time;
547         
548         if (!Mouse_installed)
549                 return 0;
550
551         mouse_handler(); //temp
552         
553         if ((button < 0) || (button >= MOUSE_MAX_BUTTONS))
554                 return 0;
555         
556         //      _disable();
557         if (!Mouse.pressed[button]) {
558                 time_down = Mouse.time_held_down[button];
559                 Mouse.time_held_down[button] = 0;
560         } else {
561                 time = timer_get_fixed_seconds();
562                 time_down = time - Mouse.time_held_down[button];
563                 Mouse.time_held_down[button] = 0;
564         }
565         //      _enable();
566         
567         return time_down;
568 }
569
570 void mouse_get_cyberman_pos( int *x, int *y )
571 {
572 }
573
574
575
576 //WHS: I made this :)
577 void hide_cursor()
578 {
579         ShowCursor(FALSE);
580 }
581
582 void show_cursor()
583 {
584         ShowCursor(TRUE);
585 }
586
587
588 /* New mouse pointer stuff for GGI/DGA */
589 //#include "cursor.h" /* cursor and mask */
590
591 typedef struct Sprite {
592         ushort width;
593         ushort height;
594         byte *pixels;
595         byte *mask;
596 } Sprite;
597
598 //Sprite mouse_sprite = { cursor_width, cursor_height, cursor_bits, cursor_mask_bits};
599
600 //byte *behind_mouse;
601 //byte behind_mouse[cursor_width*cursor_height];
602
603
604 void DrawMouse(void)
605 {
606 }
607
608
609 void EraseMouse(void)
610 {
611 }
612
613 //Should add a mode, relative, absolute
614 #define MOVE_REL 0
615 #define MOVE_ABS 1
616 //void MoveMouse(int mode, int x, int y) {
617
618 void MoveMouse(int x, int y)
619 {
620 }