ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.11
Committed: Fri Jan 21 22:08:48 2011 UTC (15 years, 9 months ago) by sf-pippijn
Branch: MAIN
Changes since 1.10: +0 -2 lines
Log Message:
not needed, anymore

File Contents

# Content
1 #include "deliantra/sender.h"
2
3 #include "dclient/input_handler.h"
4 #include "dclient/render_glyph.h"
5 #include "dclient/widgets.h"
6 #include "dclient/widgets/inventory.h"
7 #include "dclient/widgets/map.h"
8 #include "dclient/widgets/query.h"
9 #include "dclient/widgets/stats.h"
10
11 #include <ndk/application.hh>
12 #include <ndk/color.hh>
13
14 #include <curses.h>
15
16 #include <ev.h>
17
18 typedef unsigned long flags_t;
19
20 enum class flags
21 : flags_t
22 {
23 none,
24 firing = 1 << 0,
25 running = 1 << 1,
26
27 COUNT
28 };
29
30 static flags &
31 operator += (flags &lhs, flags rhs)
32 {
33 return lhs = flags (flags_t (lhs) | flags_t (rhs));
34 }
35
36 static flags &
37 operator -= (flags &lhs, flags rhs)
38 {
39 return lhs = flags (flags_t (lhs) & ~flags_t (rhs));
40 }
41
42 static bool
43 operator & (flags lhs, flags rhs)
44 {
45 return flags_t (lhs) & flags_t (rhs);
46 }
47
48
49 enum class action
50 {
51 none,
52
53 north,
54 northeast,
55 east,
56 southeast,
57 south,
58 southwest,
59 west,
60 northwest,
61
62 run,
63 fire,
64 stay_fire,
65
66 quit,
67 redraw,
68 resize,
69 maximise,
70 input_mode,
71
72 apply,
73 take,
74
75 COUNT
76 };
77
78
79 struct input_handler::pimpl
80 : sender
81 {
82 pimpl (communicator &comm, widgets &ui);
83
84 void perform (ndk::panel *sender, action cmd, action arg = action::none);
85
86 ndk::event::result on_kbd_common (ndk::keyboard const &ev);
87 ndk::event::result on_kbd_map (ndk::keyboard const &ev);
88
89 void on_command (std::string const &cmd);
90 void stdin_read_cb (ev::io &w, int revents);
91
92 widgets &ui;
93 std::string esc;
94 ev::io stdin_watcher;
95 flags state;
96 };
97
98 input_handler::pimpl::pimpl (communicator &comm, widgets &ui)
99 : sender (comm)
100 , ui (ui)
101 , state (flags::none)
102 {
103 auto kbd_common = ndk::slot (&pimpl::on_kbd_common, this);
104
105 ui.map->events ()->on_keyboard (kbd_common);
106 ui.info->events ()->on_keyboard (kbd_common);
107 ui.stats->events ()->on_keyboard (kbd_common);
108 ui.inventory->events ()->on_keyboard (kbd_common);
109 ui.container->events ()->on_keyboard (kbd_common);
110 ui.invmenu->events ()->on_keyboard (kbd_common);
111 ui.query->events ()->on_keyboard (kbd_common);
112
113 ui.map->events ()->on_keyboard (ndk::slot (&pimpl::on_kbd_map, this));
114
115 ui.input->on_commit () = ndk::slot (&pimpl::on_command, this);
116
117 stdin_watcher.set (STDIN_FILENO, ev::READ);
118 stdin_watcher.set<pimpl, &pimpl::stdin_read_cb> (this);
119 stdin_watcher.start ();
120 }
121
122 void
123 input_handler::pimpl::perform (ndk::panel *sender, action cmd, action arg)
124 {
125 if (state & flags::running)
126 {
127 send ("command", "run_stop");
128 state -= flags::running;
129 }
130 if (state & flags::firing)
131 {
132 send ("command", "fire_stop");
133 state -= flags::firing;
134 }
135
136 switch (cmd)
137 {
138 case action::none:
139 break;
140
141 // direction commands
142 case action::north: send ("command", "north" ); break;
143 case action::northeast: send ("command", "northeast"); break;
144 case action::east: send ("command", "east" ); break;
145 case action::southeast: send ("command", "southeast"); break;
146 case action::south: send ("command", "south" ); break;
147 case action::southwest: send ("command", "southwest"); break;
148 case action::west: send ("command", "west" ); break;
149 case action::northwest: send ("command", "northwest"); break;
150
151 // running
152 case action::run:
153 send ("command", "run ", int (arg));
154 state += flags::running;
155 break;
156
157 // firing
158 case action::fire:
159 send ("command", "fire ", int (arg));
160 state += flags::firing;
161 break;
162
163 case action::stay_fire:
164 send ("command", "stay fire");
165 break;
166
167 // control commands
168 case action::quit:
169 ev_break (EV_DEFAULT_UC_ EVBREAK_ALL);
170 break;
171
172 case action::redraw:
173 redrawwin (stdscr);
174 break;
175
176 case action::resize:
177 ui.resize ();
178 break;
179
180 case action::maximise:
181 if (ui.maximised)
182 ui.maximised = nullptr;
183 else
184 ui.maximised = sender;
185 perform (sender, action::resize);
186 break;
187
188 case action::input_mode:
189 ui.input->visualize ();
190 ui.input->focus ();
191 break;
192
193 // action commands
194 case action::apply:
195 send ("command", "apply");
196 break;
197
198 case action::take:
199 send ("command", "take");
200 break;
201
202 // never happens
203 case action::COUNT:
204 abort ();
205 }
206 }
207
208 ndk::event::result
209 input_handler::pimpl::on_kbd_common (ndk::keyboard const &ev)
210 {
211 switch (ev.code ())
212 {
213 case ndk::key::error:
214 throw "ERR";
215
216 // control actions
217 case ndk::key::ctrl_d:
218 case 'q':
219 perform (ev.sender (), action::quit);
220 return ndk::event::accepted;
221
222 case ndk::key::ctrl_l:
223 perform (ev.sender (), action::redraw);
224 return ndk::event::accepted;
225
226 case ndk::key::resize:
227 perform (ev.sender (), action::resize);
228 return ndk::event::accepted;
229
230 case ndk::key::F10:
231 perform (ev.sender (), action::maximise);
232 return ndk::event::accepted;
233
234 default:
235 return ndk::event::ignored;
236 }
237 }
238
239 ndk::event::result
240 input_handler::pimpl::on_kbd_map (ndk::keyboard const &ev)
241 {
242 switch (ev.code ())
243 {
244 // moving
245 case 'j':
246 case '2':
247 case ndk::key::down:
248 perform (ev.sender (), action::south);
249 return ndk::event::accepted;
250 case 'k':
251 case '8':
252 case ndk::key::up:
253 perform (ev.sender (), action::north);
254 return ndk::event::accepted;
255 case 'h':
256 case '4':
257 case ndk::key::left:
258 perform (ev.sender (), action::west);
259 return ndk::event::accepted;
260 case 'l':
261 case '6':
262 case ndk::key::right:
263 perform (ev.sender (), action::east);
264 return ndk::event::accepted;
265 case '7':
266 case ndk::key::home:
267 perform (ev.sender (), action::northwest);
268 return ndk::event::accepted;
269 case '9':
270 case ndk::key::pg_up:
271 perform (ev.sender (), action::northeast);
272 return ndk::event::accepted;
273 case '5':
274 case ndk::key::numpad_center:
275 perform (ev.sender (), action::stay_fire);
276 return ndk::event::accepted;
277 case '1':
278 case ndk::key::end:
279 perform (ev.sender (), action::southwest);
280 return ndk::event::accepted;
281 case '3':
282 case ndk::key::pg_dn:
283 perform (ev.sender (), action::southeast);
284 return ndk::event::accepted;
285
286 case ' ':
287 perform (ev.sender (), action::apply);
288 return ndk::event::accepted;
289 case ',':
290 perform (ev.sender (), action::take);
291 return ndk::event::accepted;
292 case ndk::key::enter:
293 case 'i':
294 perform (ev.sender (), action::input_mode);
295 return ndk::event::accepted;
296 case 'c':
297 ui.input->set_text ("chat ");
298 perform (ev.sender (), action::input_mode);
299 return ndk::event::accepted;
300 case '"':
301 ui.input->set_text ("say ");
302 perform (ev.sender (), action::input_mode);
303 return ndk::event::accepted;
304 case '\'':
305 ui.input->set_text ("tell ");
306 perform (ev.sender (), action::input_mode);
307 return ndk::event::accepted;
308
309 // firing
310 case 'J':
311 case ndk::key::shift_down:
312 perform (ev.sender (), action::fire, action::south);
313 return ndk::event::accepted;
314 case 'K':
315 case ndk::key::shift_up:
316 perform (ev.sender (), action::fire, action::north);
317 return ndk::event::accepted;
318 case 'H':
319 case ndk::key::shift_left:
320 perform (ev.sender (), action::fire, action::west);
321 return ndk::event::accepted;
322 case 'L':
323 case ndk::key::shift_right:
324 perform (ev.sender (), action::fire, action::east);
325 return ndk::event::accepted;
326 case ndk::key::shift_home:
327 perform (ev.sender (), action::fire, action::northwest);
328 return ndk::event::accepted;
329 case ndk::key::shift_pg_up:
330 perform (ev.sender (), action::fire, action::northeast);
331 return ndk::event::accepted;
332 case ndk::key::shift_end:
333 perform (ev.sender (), action::fire, action::southwest);
334 return ndk::event::accepted;
335 case ndk::key::shift_pg_dn:
336 perform (ev.sender (), action::fire, action::southeast);
337 return ndk::event::accepted;
338
339 // running
340 //case 'J':
341 case ndk::key::ctrl_down:
342 perform (ev.sender (), action::run, action::south);
343 return ndk::event::accepted;
344 //case 'K':
345 case ndk::key::ctrl_up:
346 perform (ev.sender (), action::run, action::north);
347 return ndk::event::accepted;
348 //case 'H':
349 case ndk::key::ctrl_left:
350 perform (ev.sender (), action::run, action::west);
351 return ndk::event::accepted;
352 //case 'L':
353 case ndk::key::ctrl_right:
354 perform (ev.sender (), action::run, action::east);
355 return ndk::event::accepted;
356 case ndk::key::ctrl_home:
357 perform (ev.sender (), action::run, action::northwest);
358 return ndk::event::accepted;
359 case ndk::key::ctrl_pg_up:
360 perform (ev.sender (), action::run, action::northeast);
361 return ndk::event::accepted;
362 case ndk::key::ctrl_end:
363 perform (ev.sender (), action::run, action::southwest);
364 return ndk::event::accepted;
365 case ndk::key::ctrl_pg_dn:
366 perform (ev.sender (), action::run, action::southeast);
367 return ndk::event::accepted;
368
369 case ndk::key::ctrl_l:
370 case ndk::key::F10:
371 case ndk::key::resize:
372 case ndk::key::tab:
373 return ndk::event::ignored;
374
375 case ndk::key::unknown:
376 return ndk::event::ignored;
377
378 default:
379 if (getenv ("DCLIENT_FATAL"))
380 throw ev.code ();
381 else
382 {
383 ui.info->add_text (ndi_color (3, 0), "unknown keycode: 0%03o\n", ev.code ());
384 ui.info->visualize ();
385 return ndk::event::ignored;
386 }
387 }
388 }
389
390 void
391 input_handler::pimpl::on_command (std::string const &cmd)
392 {
393 ui.input->set_text ("");
394
395 if (!cmd.empty ())
396 send ("command", cmd);
397 else
398 {
399 ui.map->focus ();
400 ui.input->hide ();
401 ndk::app->cursor_off (); // FIXME: should be done automatically
402 }
403 }
404
405 void
406 input_handler::pimpl::stdin_read_cb (ev::io &w, int revents)
407 {
408 ndk::app->process (getch ());
409 }
410
411
412 input_handler::input_handler (communicator &comm, widgets &ui)
413 : impl (new pimpl (comm, ui))
414 {
415 }
416
417 input_handler::~input_handler ()
418 {
419 delete impl;
420 }