Merge branch '4524_cleanup'
[midnight-commander.git] / lib / widget / radio.c
blob94463f6276e546424ee6767546014e99aaae94da
1 /*
2 Widgets for the Midnight Commander
4 Copyright (C) 1994-2024
5 Free Software Foundation, Inc.
7 Authors:
8 Radek Doulik, 1994, 1995
9 Miguel de Icaza, 1994, 1995
10 Jakub Jelinek, 1995
11 Andrej Borsenkow, 1996
12 Norbert Warmuth, 1997
13 Andrew Borodin <aborodin@vmail.ru>, 2009-2022
15 This file is part of the Midnight Commander.
17 The Midnight Commander is free software: you can redistribute it
18 and/or modify it under the terms of the GNU General Public License as
19 published by the Free Software Foundation, either version 3 of the License,
20 or (at your option) any later version.
22 The Midnight Commander is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 /** \file radio.c
32 * \brief Source: WRadui widget (radiobuttons)
35 #include <config.h>
37 #include <stdlib.h>
39 #include "lib/global.h"
41 #include "lib/tty/tty.h"
42 #include "lib/widget.h"
44 /*** global variables ****************************************************************************/
46 const global_keymap_t *radio_map = NULL;
48 /*** file scope macro definitions ****************************************************************/
50 /*** file scope type declarations ****************************************************************/
52 /*** forward declarations (file scope functions) *************************************************/
54 /*** file scope variables ************************************************************************/
56 /* --------------------------------------------------------------------------------------------- */
57 /*** file scope functions ************************************************************************/
58 /* --------------------------------------------------------------------------------------------- */
60 static cb_ret_t
61 radio_execute_cmd (WRadio * r, long command)
63 cb_ret_t ret = MSG_HANDLED;
64 Widget *w = WIDGET (r);
66 switch (command)
68 case CK_Up:
69 case CK_Top:
70 if (r->pos == 0)
71 return MSG_NOT_HANDLED;
73 if (command == CK_Top)
74 r->pos = 0;
75 else
76 r->pos--;
77 widget_draw (w);
78 return MSG_HANDLED;
80 case CK_Down:
81 case CK_Bottom:
82 if (r->pos == r->count - 1)
83 return MSG_NOT_HANDLED;
85 if (command == CK_Bottom)
86 r->pos = r->count - 1;
87 else
88 r->pos++;
89 widget_draw (w);
90 return MSG_HANDLED;
92 case CK_Select:
93 r->sel = r->pos;
94 widget_set_state (w, WST_FOCUSED, TRUE); /* Also draws the widget */
95 send_message (w->owner, w, MSG_NOTIFY, 0, NULL);
96 return MSG_HANDLED;
98 default:
99 ret = MSG_NOT_HANDLED;
100 break;
103 return ret;
106 /* --------------------------------------------------------------------------------------------- */
108 /* Return MSG_HANDLED if we want a redraw */
109 static cb_ret_t
110 radio_key (WRadio * r, int key)
112 long command;
114 command = widget_lookup_key (WIDGET (r), key);
115 if (command == CK_IgnoreKey)
116 return MSG_NOT_HANDLED;
117 return radio_execute_cmd (r, command);
120 /* --------------------------------------------------------------------------------------------- */
122 static cb_ret_t
123 radio_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
125 WRadio *r = RADIO (w);
126 int i;
128 switch (msg)
130 case MSG_HOTKEY:
131 for (i = 0; i < r->count; i++)
133 if (r->texts[i].hotkey != NULL)
135 int c;
137 c = g_ascii_tolower ((gchar) r->texts[i].hotkey[0]);
138 if (c != parm)
139 continue;
140 r->pos = i;
142 /* Take action */
143 send_message (w, sender, MSG_ACTION, CK_Select, data);
144 return MSG_HANDLED;
147 return MSG_NOT_HANDLED;
149 case MSG_KEY:
150 return radio_key (r, parm);
152 case MSG_ACTION:
153 return radio_execute_cmd (r, parm);
155 case MSG_CURSOR:
156 widget_gotoyx (r, r->pos, 1);
157 return MSG_HANDLED;
159 case MSG_DRAW:
161 gboolean focused;
163 focused = widget_get_state (w, WST_FOCUSED);
165 for (i = 0; i < r->count; i++)
167 widget_selectcolor (w, i == r->pos && focused, FALSE);
168 widget_gotoyx (w, i, 0);
169 tty_draw_hline (w->rect.y + i, w->rect.x, ' ', w->rect.cols);
170 tty_print_string ((r->sel == i) ? "(*) " : "( ) ");
171 hotkey_draw (w, r->texts[i], i == r->pos && focused);
174 return MSG_HANDLED;
177 case MSG_DESTROY:
178 for (i = 0; i < r->count; i++)
179 hotkey_free (r->texts[i]);
180 g_free (r->texts);
181 return MSG_HANDLED;
183 default:
184 return widget_default_callback (w, sender, msg, parm, data);
188 /* --------------------------------------------------------------------------------------------- */
190 static void
191 radio_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
193 switch (msg)
195 case MSG_MOUSE_DOWN:
196 RADIO (w)->pos = event->y;
197 widget_select (w);
198 break;
200 case MSG_MOUSE_CLICK:
201 RADIO (w)->pos = event->y;
202 send_message (w, NULL, MSG_ACTION, CK_Select, NULL);
203 send_message (w->owner, w, MSG_POST_KEY, ' ', NULL);
204 break;
206 default:
207 break;
211 /* --------------------------------------------------------------------------------------------- */
212 /*** public functions ****************************************************************************/
213 /* --------------------------------------------------------------------------------------------- */
215 WRadio *
216 radio_new (int y, int x, int count, const char **texts)
218 WRect r0 = { y, x, count, 1 };
219 WRadio *r;
220 Widget *w;
221 int i, wmax = 0;
223 r = g_new (WRadio, 1);
224 w = WIDGET (r);
226 /* Compute the longest string */
227 r->texts = g_new (hotkey_t, count);
229 for (i = 0; i < count; i++)
231 int width;
233 r->texts[i] = hotkey_new (texts[i]);
234 width = hotkey_width (r->texts[i]);
235 wmax = MAX (width, wmax);
238 /* 4 is width of "(*) " */
239 r0.cols = 4 + wmax;
240 widget_init (w, &r0, radio_callback, radio_mouse_callback);
241 w->options |= WOP_SELECTABLE | WOP_WANT_CURSOR | WOP_WANT_HOTKEY;
242 w->keymap = radio_map;
244 r->pos = 0;
245 r->sel = 0;
246 r->count = count;
248 return r;
251 /* --------------------------------------------------------------------------------------------- */