1 /*
2    Handle any events in application.
3    Manage events: add, delete, destroy, search
4 
5    Copyright (C) 2011-2021
6    Free Software Foundation, Inc.
7 
8    Written by:
9    Slava Zanko <slavazanko@gmail.com>, 2011.
10 
11    This file is part of the Midnight Commander.
12 
13    The Midnight Commander is free software: you can redistribute it
14    and/or modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation, either version 3 of the License,
16    or (at your option) any later version.
17 
18    The Midnight Commander is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #include <config.h>
28 
29 #include "lib/global.h"
30 #include "lib/util.h"
31 #include "lib/event.h"
32 
33 #include "internal.h"
34 
35 /*** global variables ****************************************************************************/
36 
37 /*** file scope macro definitions ****************************************************************/
38 
39 /*** file scope type declarations ****************************************************************/
40 
41 /*** file scope variables ************************************************************************/
42 
43 /*** file scope functions ************************************************************************/
44 /* --------------------------------------------------------------------------------------------- */
45 
46 static void
mc_event_group_destroy_value(gpointer data)47 mc_event_group_destroy_value (gpointer data)
48 {
49     GPtrArray *callbacks;
50 
51     callbacks = (GPtrArray *) data;
52     g_ptr_array_foreach (callbacks, (GFunc) g_free, NULL);
53     g_ptr_array_free (callbacks, TRUE);
54 }
55 
56 /* --------------------------------------------------------------------------------------------- */
57 
58 
59 /* --------------------------------------------------------------------------------------------- */
60 /*** public functions ****************************************************************************/
61 /* --------------------------------------------------------------------------------------------- */
62 
63 gboolean
mc_event_add(const gchar * event_group_name,const gchar * event_name,mc_event_callback_func_t event_callback,gpointer event_init_data,GError ** mcerror)64 mc_event_add (const gchar * event_group_name, const gchar * event_name,
65               mc_event_callback_func_t event_callback, gpointer event_init_data, GError ** mcerror)
66 {
67 
68     GTree *event_group;
69     GPtrArray *callbacks;
70     mc_event_callback_t *cb;
71 
72     mc_return_val_if_error (mcerror, FALSE);
73 
74     if (mc_event_grouplist == NULL || event_group_name == NULL || event_name == NULL
75         || event_callback == NULL)
76     {
77         mc_propagate_error (mcerror, 0, "%s", _("Check input data! Some of parameters are NULL!"));
78         return FALSE;
79     }
80 
81     event_group = mc_event_get_event_group_by_name (event_group_name, TRUE, mcerror);
82     if (event_group == NULL)
83         return FALSE;
84 
85     callbacks = mc_event_get_event_by_name (event_group, event_name, TRUE, mcerror);
86     if (callbacks == NULL)
87         return FALSE;
88 
89     cb = mc_event_is_callback_in_array (callbacks, event_callback, event_init_data);
90     if (cb == NULL)
91     {
92         cb = g_new0 (mc_event_callback_t, 1);
93         cb->callback = event_callback;
94         g_ptr_array_add (callbacks, (gpointer) cb);
95     }
96     cb->init_data = event_init_data;
97     return TRUE;
98 }
99 
100 /* --------------------------------------------------------------------------------------------- */
101 
102 void
mc_event_del(const gchar * event_group_name,const gchar * event_name,mc_event_callback_func_t event_callback,gpointer event_init_data)103 mc_event_del (const gchar * event_group_name, const gchar * event_name,
104               mc_event_callback_func_t event_callback, gpointer event_init_data)
105 {
106     GTree *event_group;
107     GPtrArray *callbacks;
108     mc_event_callback_t *cb;
109 
110     if (mc_event_grouplist == NULL || event_group_name == NULL || event_name == NULL
111         || event_callback == NULL)
112         return;
113 
114     event_group = mc_event_get_event_group_by_name (event_group_name, FALSE, NULL);
115     if (event_group == NULL)
116         return;
117 
118     callbacks = mc_event_get_event_by_name (event_group, event_name, FALSE, NULL);
119     if (callbacks == NULL)
120         return;
121 
122     cb = mc_event_is_callback_in_array (callbacks, event_callback, event_init_data);
123 
124     if (cb == NULL)
125         return;
126 
127     g_ptr_array_remove (callbacks, (gpointer) cb);
128     g_free ((gpointer) cb);
129 }
130 
131 /* --------------------------------------------------------------------------------------------- */
132 
133 void
mc_event_destroy(const gchar * event_group_name,const gchar * event_name)134 mc_event_destroy (const gchar * event_group_name, const gchar * event_name)
135 {
136     GTree *event_group;
137 
138     if (mc_event_grouplist == NULL || event_group_name == NULL || event_name == NULL)
139         return;
140 
141     event_group = mc_event_get_event_group_by_name (event_group_name, FALSE, NULL);
142     g_tree_remove (event_group, (gconstpointer) event_name);
143 }
144 
145 /* --------------------------------------------------------------------------------------------- */
146 
147 void
mc_event_group_del(const gchar * event_group_name)148 mc_event_group_del (const gchar * event_group_name)
149 {
150 
151     if (mc_event_grouplist != NULL && event_group_name != NULL)
152         g_tree_remove (mc_event_grouplist, (gconstpointer) event_group_name);
153 }
154 
155 /* --------------------------------------------------------------------------------------------- */
156 
157 GTree *
mc_event_get_event_group_by_name(const gchar * event_group_name,gboolean create_new,GError ** mcerror)158 mc_event_get_event_group_by_name (const gchar * event_group_name, gboolean create_new,
159                                   GError ** mcerror)
160 {
161     GTree *event_group;
162 
163     mc_return_val_if_error (mcerror, FALSE);
164 
165     event_group = (GTree *) g_tree_lookup (mc_event_grouplist, (gconstpointer) event_group_name);
166     if (event_group == NULL && create_new)
167     {
168         event_group =
169             g_tree_new_full ((GCompareDataFunc) g_ascii_strcasecmp,
170                              NULL,
171                              (GDestroyNotify) g_free,
172                              (GDestroyNotify) mc_event_group_destroy_value);
173         if (event_group == NULL)
174         {
175             mc_propagate_error (mcerror, 0, _("Unable to create group '%s' for events!"),
176                                 event_group_name);
177             return NULL;
178         }
179         g_tree_insert (mc_event_grouplist, g_strdup (event_group_name), (gpointer) event_group);
180     }
181     return event_group;
182 }
183 
184 /* --------------------------------------------------------------------------------------------- */
185 
186 GPtrArray *
mc_event_get_event_by_name(GTree * event_group,const gchar * event_name,gboolean create_new,GError ** mcerror)187 mc_event_get_event_by_name (GTree * event_group, const gchar * event_name, gboolean create_new,
188                             GError ** mcerror)
189 {
190     GPtrArray *callbacks;
191 
192     mc_return_val_if_error (mcerror, FALSE);
193 
194     callbacks = (GPtrArray *) g_tree_lookup (event_group, (gconstpointer) event_name);
195     if (callbacks == NULL && create_new)
196     {
197         callbacks = g_ptr_array_new ();
198         if (callbacks == NULL)
199         {
200             mc_propagate_error (mcerror, 0, _("Unable to create event '%s'!"), event_name);
201             return NULL;
202         }
203         g_tree_insert (event_group, g_strdup (event_name), (gpointer) callbacks);
204     }
205     return callbacks;
206 }
207 
208 /* --------------------------------------------------------------------------------------------- */
209 
210 mc_event_callback_t *
mc_event_is_callback_in_array(GPtrArray * callbacks,mc_event_callback_func_t event_callback,gpointer event_init_data)211 mc_event_is_callback_in_array (GPtrArray * callbacks, mc_event_callback_func_t event_callback,
212                                gpointer event_init_data)
213 {
214     guint array_index;
215 
216     for (array_index = 0; array_index < callbacks->len; array_index++)
217     {
218         mc_event_callback_t *cb = g_ptr_array_index (callbacks, array_index);
219         if (cb->callback == event_callback && cb->init_data == event_init_data)
220             return cb;
221     }
222     return NULL;
223 }
224 
225 /* --------------------------------------------------------------------------------------------- */
226