1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  * Copyright 2010,2015 Jesse Allen
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 //Filename    : OMOUSE.H
23 //Description : Input event class
24 
25 #ifndef __OMOUSE_H
26 #define __OMOUSE_H
27 
28 //-------- Define macro constant --------//
29 //
30 // Button id, for Mouse internal use only,
31 // not appeal to mouse driver parameters
32 //
33 //---------------------------------------//
34 
35 // event_type
36 enum MouseEventType
37 {
38 	LEFT_BUTTON = 0,
39 	RIGHT_BUTTON = LEFT_BUTTON+1,
40 	KEY_PRESS = 2,
41 	LEFT_BUTTON_RELEASE = 4,
42 	RIGHT_BUTTON_RELEASE = LEFT_BUTTON_RELEASE+1,
43 	KEY_RELEASE = 6,
44 	KEY_TYPING = 7,
45 };
46 
47 enum KeyEventType : int
48 {
49 	KEYEVENT_UNSET = 0,
50 
51 	KEYEVENT_FIRM_BUILD,
52 	KEYEVENT_FIRM_PATROL,
53 
54 	KEYEVENT_TOWN_RECRUIT,
55 	KEYEVENT_TOWN_TRAIN,
56 
57 	KEYEVENT_UNIT_BUILD,
58 	KEYEVENT_UNIT_RETURN,
59 	KEYEVENT_UNIT_SETTLE,
60 	KEYEVENT_UNIT_UNLOAD,
61 
62 	KEYEVENT_BUILD_BASE,
63 	KEYEVENT_BUILD_CAMP,
64 	KEYEVENT_BUILD_FACTORY,
65 	KEYEVENT_BUILD_HARBOR,
66 	KEYEVENT_BUILD_INN,
67 	KEYEVENT_BUILD_MARKET,
68 	KEYEVENT_BUILD_MINE,
69 	KEYEVENT_BUILD_MONSTER,
70 	KEYEVENT_BUILD_RESEARCH,
71 	KEYEVENT_BUILD_WAR_FACTORY,
72 
73 	KEYEVENT_MAP_MODE_CYCLE,
74 	KEYEVENT_MAP_MODE0,
75 	KEYEVENT_MAP_MODE1,
76 	KEYEVENT_MAP_MODE2,
77 	KEYEVENT_REPORT_OPAQUE_TOGGLE,
78 	KEYEVENT_CLEAR_NEWS,
79 	KEYEVENT_OPEN_DIPLOMATIC_MSG,
80 	KEYEVENT_OPEN_OPTION_MENU,
81 
82 	KEYEVENT_TUTOR_PREV,
83 	KEYEVENT_TUTOR_NEXT,
84 
85 	KEYEVENT_SAVE_GAME,
86 	KEYEVENT_LOAD_GAME,
87 
88 	KEYEVENT_OBJECT_PREV,
89 	KEYEVENT_OBJECT_NEXT,
90 	KEYEVENT_NATION_OBJECT_PREV,
91 	KEYEVENT_NATION_OBJECT_NEXT,
92 
93 	KEYEVENT_GOTO_RAW,
94 	KEYEVENT_GOTO_KING,
95 	KEYEVENT_GOTO_GENERAL,
96 	KEYEVENT_GOTO_SPY,
97 	KEYEVENT_GOTO_SHIP,
98 	KEYEVENT_GOTO_CAMP,
99 
100 	KEYEVENT_CHEAT_ENABLE1,
101 	KEYEVENT_CHEAT_ENABLE2,
102 	KEYEVENT_CHEAT_ENABLE3,
103 
104 	KEYEVENT_MANUF_QUEUE_UP,
105 	KEYEVENT_MANUF_QUEUE_DOWN,
106 	KEYEVENT_MANUF_QUEUE_ADD,
107 	KEYEVENT_MANUF_QUEUE_ADD_BATCH,
108 	KEYEVENT_MANUF_QUEUE_REMOVE,
109 	KEYEVENT_MANUF_QUEUE_REMOVE_BATCH,
110 
111 	KEYEVENT_MAX
112 };
113 #define GETKEY(n) mouse.get_key_code(n)
114 #define ISKEY(n) mouse.is_key_event(n)
115 
116 //------- Define struct MouseEvent --------//
117 
118 struct MouseEvent               // event buffer structure
119 {
120 	MouseEventType	event_type;   // mouse state
121 
122 	unsigned long  time;               // time event occurred
123 	unsigned short skey_state;   // speical key state, such as LEFT_SHIFT_KEY_MASK ...
124 	// int	state;              // state mask of mouse button
125 
126 	int      x, y;               // mousecursor coordinates
127 	unsigned scan_code;          // if scan_code>0 then it's a key press event
128 	char typing;
129 };
130 
131 #define LEFT_BUTTON_MASK	1
132 #define RIGHT_BUTTON_MASK	2
133 
134 
135 // bit flag of any skey_state, event_skey_state
136 #define LEFT_SHIFT_KEY_MASK 0x001
137 #define RIGHT_SHIFT_KEY_MASK 0x002
138 #define SHIFT_KEY_MASK 0x003
139 #define LEFT_CONTROL_KEY_MASK 0x004
140 #define RIGHT_CONTROL_KEY_MASK 0x008
141 #define CONTROL_KEY_MASK 0x00c
142 #define LEFT_ALT_KEY_MASK 0x010
143 #define RIGHT_ALT_KEY_MASK 0x020
144 #define ALT_KEY_MASK 0x030
145 #define NUM_LOCK_STATE_MASK 0x040
146 #define CAP_LOCK_STATE_MASK 0x080
147 #define SCROLL_LOCK_STATE_MASK 0x100
148 #define INSERT_STATE_MASK 0x200
149 #define GRAPH_KEY_MASK 0x400
150 
151 //----- Define the upper limit for mouse coordination ------//
152 
153 #define MOUSE_X_UPPER_LIMIT   (VGA_WIDTH-5)
154 #define MOUSE_Y_UPPER_LIMIT	(VGA_HEIGHT-5)
155 
156 //------ Default settting ---------//
157 
158 #define DEFAULT_DOUBLE_SPEED_THRESHOLD 8
159 #define DEFAULT_TRIPLE_SPEED_THRESHOLD 16
160 
161 //-------- Define struct MouseClick -------//
162 
163 struct MouseClick               // MultiClick buffer structure
164 {
165 	int x, y;
166 	int release_x, release_y;	// where mouse is release
167 	int count;          // number of clicks
168 	unsigned long time;           // time of last click
169 	unsigned long release_time;	 // time of last release
170 };
171 
172 //--------- Define class Mouse ------------//
173 
174 class Mouse
175 {
176 private:
177 	char  init_flag;
178 	char* vga_update_buf;
179 
180 	// ------ mouse setting ---------- //
181 	int	double_speed_threshold;				// default DEFAULT_DOUBLE_SPEED_THRESHOLD
182 	int	triple_speed_threshold;				// default DEFAULT_TRIPLE_SPEED_THRESHOLD
183 
184 	//-------- click buffer ---------//
185 	MouseClick click_buffer[2];    // left button & right button only
186 
187 	//-------- event buffer ---------//
188 
189 	enum { EVENT_BUFFER_SIZE = 20 };  // No. of events can be stored in buffer
190 
191 	MouseEvent event_buffer[EVENT_BUFFER_SIZE];
192 
193 	int head_ptr;        // head pointer to the event buffer
194 	int tail_ptr;        // tail pointer to the event buffer
195 
196 public:
197 	char handle_flicking;
198 
199 	//------- real-time mouse state -------//
200 
201 	int cur_x, cur_y;
202 	int left_press, right_press;
203 
204 	//------- real-time keyboard state ---------//
205 	unsigned short skey_state;		// such as LEFT_SHIFT_KEY_MASK
206 
207 	//------- boundary of mouse cursor hot spot --------//
208 	int	bound_x1;
209 	int	bound_y1;
210 	int	bound_x2;
211 	int	bound_y2;
212 
213 	//-------- click & key buffer ---------//
214 
215 	unsigned short event_skey_state;
216 	char has_mouse_event;		 // if has_mouse_event, mouse_event_type is valid
217 	MouseEventType mouse_event_type;
218 											 // use : LEFT_BUTTON=0, RIGHT_BUTTON=1
219 	unsigned scan_code;             // key pressed, keyboard event
220 	unsigned key_code;				// converted from scan_code and event_skey_state
221 	unsigned unique_key_code;	// any key pressed unfiltered by modifiers
222 	char typing_char;
223 
224 	//-------- wheel/touch scrolling ---------//
225 
226 	bool scrolling = false;
227 	int scroll_sensitivity = 10;
228 	int scroll_x = 0, scroll_y = 0;
229 	double scroll_prev_y = 0.0, scroll_prev_x = 0.0;
230 
231 public:
232 	Mouse();
233 	~Mouse();
234 
235 	void	init();
236 	void	init_key();
237 	void	deinit();
238 
239 	void 	add_event(MouseEvent *);
240 	void 	add_event(MouseEventType type);
241 	void 	add_key_event(unsigned, unsigned long);
242 	int  	get_event();
243 	void	poll_event();
244 	void    process_mouse_motion(int x, int y);
245 	// #### begin Gilbert 31/10 #########//
246 	void	update_skey_state();
247 	// #### end Gilbert 31/10 #########//
248 
249 	void 	show();
250 	void 	hide();
251 	void 	hide_area(int,int,int,int);
252 	void 	show_area();
253 
254 	//--- functions for real-time mouse state accessing ---//
255 
256 	int  	in_area(int,int,int,int);
257 	int  	press_area(int,int,int,int,int=0);
258 	int 	wait_press(int timeOutSecond=0);
259 	bool    get_scroll(int * x, int * y);
260 	void    process_scroll(int x, int y);
261 	void    process_scroll(double x, double y);
262 	void    end_scroll();
263 
264 	//---- functions of mouse cursor boundary ------//
265 	void	set_boundary(int, int, int, int);
266 	void	reset_boundary();
267 
268 	//----- functions for queue event accessing ----//
269 
270 	int  	single_click(int,int,int,int,int=0);
271 	int  	double_click(int,int,int,int,int=0);
272 	int  	any_click   (int,int,int,int,int=0);
273 	int  	any_click(int=0);
274 	int	release_click(int,int,int,int,int=0);
275 
276 	int  	click_x(int buttonId=0)     { return click_buffer[buttonId].x; }
277 	int  	click_y(int buttonId=0)     { return click_buffer[buttonId].y; }
278 	int  	release_x(int buttonId=0)   { return click_buffer[buttonId].release_x; }
279 	int  	release_y(int buttonId=0)   { return click_buffer[buttonId].release_y; }
280 	int  	click_count(int buttonId=0) { return click_buffer[buttonId].count; }
281 
is_mouse_event()282 	int	is_mouse_event()            { return has_mouse_event; }
is_key_event()283 	int	is_key_event()              { return scan_code; }
is_any_event()284 	int	is_any_event()              { return has_mouse_event || scan_code; }
is_press_button_event()285 	int	is_press_button_event()     { return has_mouse_event && (mouse_event_type == LEFT_BUTTON || mouse_event_type == RIGHT_BUTTON); }
is_release_button_event()286 	int	is_release_button_event()   { return has_mouse_event && (mouse_event_type == LEFT_BUTTON_RELEASE || mouse_event_type == RIGHT_BUTTON_RELEASE); }
287 
288 	void	reset_click();
289 
290 	static int is_key(unsigned keyCode, unsigned short skeyState, unsigned short charValue, unsigned flags = 0 );
291 	static int is_key(unsigned keyCode, unsigned short skeyState, char *keyStr, unsigned flags = 0 );
292 	// see omouse2.h for flags
293 
294 	void disp_count_start();
295 	void disp_count_end();
296 
297 	int bind_key(KeyEventType key_event, const char *key);
298 	int is_key_event(KeyEventType key_event);
299 	unsigned get_key_code(KeyEventType key_event);
300 	void add_typing_event(char *text, unsigned long timeStamp);
301 
302 private:
303 	int micky_to_displacement(int d);
304 };
305 //---------- End of define class ---------------//
306 
307 extern Mouse mouse;
308 
309 #endif
310