1 /*
2 Widgets for the Midnight Commander
3
4 Copyright (C) 1994-2025
5 Free Software Foundation, Inc.
6
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
14
15 This file is part of the Midnight Commander.
16
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.
21
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.
26
27 You should have received a copy of the GNU General Public License
28 along with this program. If not, see <https://www.gnu.org/licenses/>.
29 */
30
31 /** \file check.c
32 * \brief Source: WCheck widget (checkbutton)
33 */
34
35 #include <config.h>
36
37 #include <stdlib.h>
38
39 #include "lib/global.h"
40
41 #include "lib/tty/tty.h"
42 #include "lib/widget.h"
43
44 /*** global variables ****************************************************************************/
45
46 /*** file scope macro definitions ****************************************************************/
47
48 /*** file scope type declarations ****************************************************************/
49
50 /*** forward declarations (file scope functions) *************************************************/
51
52 /*** file scope variables ************************************************************************/
53
54 /* --------------------------------------------------------------------------------------------- */
55 /*** file scope functions ************************************************************************/
56 /* --------------------------------------------------------------------------------------------- */
57
58 static cb_ret_t
59 check_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
60 {
61 WCheck *c = CHECK (w);
62
63 switch (msg)
64 {
65 case MSG_HOTKEY:
66 if (c->text.hotkey != NULL)
67 {
68 if (g_ascii_tolower ((gchar) c->text.hotkey[0]) == parm)
69 {
70 // make action
71 send_message (w, sender, MSG_KEY, ' ', data);
72 return MSG_HANDLED;
73 }
74 }
75 return MSG_NOT_HANDLED;
76
77 case MSG_KEY:
78 if (parm != ' ')
79 return MSG_NOT_HANDLED;
80 c->state = !c->state;
81 widget_draw (w);
82 send_message (w->owner, w, MSG_NOTIFY, 0, NULL);
83 return MSG_HANDLED;
84
85 case MSG_CURSOR:
86 widget_gotoyx (w, 0, 1);
87 return MSG_HANDLED;
88
89 case MSG_DRAW:
90 {
91 gboolean focused;
92
93 focused = widget_get_state (w, WST_FOCUSED);
94 widget_selectcolor (w, focused, FALSE);
95 widget_gotoyx (w, 0, 0);
96 tty_print_string (c->state ? "[x] " : "[ ] ");
97 hotkey_draw (w, c->text, focused);
98 return MSG_HANDLED;
99 }
100
101 case MSG_DESTROY:
102 hotkey_free (c->text);
103 return MSG_HANDLED;
104
105 default:
106 return widget_default_callback (w, sender, msg, parm, data);
107 }
108 }
109
110 /* --------------------------------------------------------------------------------------------- */
111
112 static void
113 check_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
114 {
115 (void) event;
116
117 switch (msg)
118 {
119 case MSG_MOUSE_DOWN:
120 widget_select (w);
121 break;
122
123 case MSG_MOUSE_CLICK:
124 send_message (w, NULL, MSG_KEY, ' ', NULL);
125 send_message (w->owner, w, MSG_POST_KEY, ' ', NULL);
126 break;
127
128 default:
129 break;
130 }
131 }
132
133 /* --------------------------------------------------------------------------------------------- */
134 /*** public functions ****************************************************************************/
135 /* --------------------------------------------------------------------------------------------- */
136
137 WCheck *
138 check_new (int y, int x, gboolean state, const char *text)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
139 {
140 WRect r = { y, x, 1, 1 };
141 WCheck *c;
142 Widget *w;
143
144 c = g_new (WCheck, 1);
145 w = WIDGET (c);
146 c->text = hotkey_new (text);
147 // 4 is width of "[X] "
148 r.cols = 4 + hotkey_width (c->text);
149 widget_init (w, &r, check_callback, check_mouse_callback);
150 w->options |= WOP_SELECTABLE | WOP_WANT_CURSOR | WOP_WANT_HOTKEY;
151 c->state = state;
152
153 return c;
154 }
155
156 /* --------------------------------------------------------------------------------------------- */
157
158 void
159 check_set_text (WCheck *check, const char *text)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
160 {
161 Widget *w = WIDGET (check);
162 hotkey_t hk;
163
164 hk = hotkey_new (text);
165 if (hotkey_equal (check->text, hk))
166 {
167 hotkey_free (hk);
168 return;
169 }
170
171 hotkey_free (check->text);
172 check->text = hk;
173
174 if (check->text.start[0] == '\0' && check->text.hotkey == NULL && check->text.end == NULL)
175 w->rect.cols = 3; // "[ ]"
176 else
177 w->rect.cols = 4 + hotkey_width (check->text); // "[ ] text"
178
179 widget_draw (w);
180 }
181
182 /* --------------------------------------------------------------------------------------------- */