1 /* mode.c - handle the program's modes in a consistent way
2 *
3 * Copyright (C) 2000 Jochen Voss. */
4
5 static const char rcsid[] = "$Id: mode.c 4839 2003-04-13 16:50:02Z voss $";
6
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdlib.h>
13
14 #include "moon-buggy.h"
15 #include "darray.h"
16
17
18 static const struct mode *current;
19 static int mode_entered, mode_seed;
20
21
22 struct mode *
new_mode(void)23 new_mode (void)
24 /* Allocate a new mode struct. */
25 {
26 struct mode *res = xmalloc (sizeof (struct mode));
27 res->enter = NULL;
28 res->leave = NULL;
29 res->redraw = NULL;
30
31 DA_INIT (res->keys, struct binding);
32 res->keypress = NULL;
33
34 return res;
35 }
36
37 void
mode_add_key(struct mode * m,int meanings,const char * desc,int res)38 mode_add_key (struct mode *m, int meanings, const char *desc, int res)
39 /* Add a key binding to mode M.
40 * MEANINGS should a combination (via |) of `mbk_key' values, DESC is
41 * the label to display near the bottom of the screen. RES is passed
42 * through to `keypress' handler. */
43 {
44 struct binding *keys;
45
46 DA_ADD_EMPTY (m->keys, struct binding, keys);
47 keys->meanings = meanings;
48 keys->desc = desc;
49 keys->res = res;
50 }
51
52 void
mode_complete(struct mode * m)53 mode_complete (struct mode *m)
54 /* This must be called at the very end of each mode's initialisation. */
55 {
56 mode_add_key (m, mbk_redraw, "redraw", 0);
57 }
58
59 void
mode_change(const struct mode * m,int seed)60 mode_change (const struct mode *m, int seed)
61 /* Change into new mode M. Pass SEED to the `enter' handler. */
62 {
63 if (mode_entered && current->leave) current->leave ();
64
65 current = m;
66 mode_entered = 0;
67 mode_seed = seed;
68 }
69
70 static void
mode_enter(void)71 mode_enter (void)
72 {
73 werase (moon);
74 wnoutrefresh (moon);
75 if (! current) return;
76
77 if (current->enter) current->enter (mode_seed);
78 mode_entered = 1;
79 }
80
81 void
mode_update(void)82 mode_update (void)
83 /* Flush queued mode updates. */
84 {
85 if (! mode_entered) {
86 clear_queue ();
87 mode_enter ();
88 mode_redraw ();
89 }
90 doupdate ();
91 }
92
93 void
mode_redraw(void)94 mode_redraw (void)
95 /* Make the current mode redraw the screen but leave the status message intact.
96 * This is also called after the screen is resized. */
97 {
98 if (! mode_entered) return;
99 describe_keys (current->keys.used, current->keys.data);
100 if (current->redraw) current->redraw ();
101 doupdate ();
102 }
103
104 int
mode_keypress(game_time t,int meaning)105 mode_keypress (game_time t, int meaning)
106 /* Feed a keypress with meaning MEANING to the current mode.
107 * Return 1 if the keypress could be processed, and 0 else. */
108 {
109 int i;
110
111 if (meaning == mbk_redraw) {
112 clear_windows ();
113 mode_redraw ();
114 return 1;
115 }
116 for (i=0; i<current->keys.used; ++i) {
117 if (current->keys.data[i].meanings & meaning) {
118 current->keypress (t, current->keys.data[i].res);
119 return 1;
120 }
121 }
122 return 0;
123 }
124
125 void
mode_signal(int signum)126 mode_signal (int signum)
127 /* Feed signal SIGNUM to the current mode. */
128 {
129 if (current->signal) current->signal (signum);
130 }
131