ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.4
Committed: Mon Oct 18 15:38:07 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.3: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

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