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