1 /*
2 * device_name_form.c - ask for sound control device name
3 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "aconfig.h"
20 #include <stdlib.h>
21 #include <string.h>
22 #include CURSESINC
23 #include <form.h>
24 #include "gettext_curses.h"
25 #include "die.h"
26 #include "mem.h"
27 #include "utils.h"
28 #include "colors.h"
29 #include "widget.h"
30 #include "mixer_widget.h"
31 #include "card_select.h"
32 #include "device_name.h"
33
34 static struct widget form_widget;
35 static FIELD *fields[3];
36 static FORM *form;
37
dup_current_name(void)38 static char *dup_current_name(void)
39 {
40 int rows, cols, max, i;
41 char *s;
42
43 if (form_driver(form, REQ_VALIDATION) == E_OK) {
44 dynamic_field_info(fields[1], &rows, &cols, &max);
45 s = ccalloc(1, cols + 1);
46 memcpy(s, field_buffer(fields[1], 0), cols);
47 for (i = strlen(s) - 1; i >= 0 && s[i] == ' '; --i)
48 s[i] = '\0';
49 return s;
50 } else {
51 return cstrdup("");
52 }
53 }
54
on_key_enter(void)55 static void on_key_enter(void)
56 {
57 char *s;
58 bool ok;
59
60 s = dup_current_name();
61 ok = select_card_by_name(s);
62 free(s);
63 if (ok) {
64 form_widget.close();
65 close_card_select_list();
66 }
67 }
68
on_form_key(int key)69 static void on_form_key(int key)
70 {
71 static const struct {
72 int key;
73 int request;
74 } key_map[] = {
75 { KEY_LEFT, REQ_PREV_CHAR },
76 { KEY_RIGHT, REQ_NEXT_CHAR },
77 { KEY_HOME, REQ_BEG_FIELD },
78 { KEY_BACKSPACE, REQ_DEL_PREV },
79 { 127, REQ_DEL_PREV },
80 { KEY_DC, REQ_DEL_CHAR },
81 { KEY_BEG, REQ_BEG_FIELD },
82 { KEY_END, REQ_END_FIELD },
83 };
84 unsigned int i;
85
86 if (key >= 32 && key < 256 && key != 127) {
87 form_driver(form, key);
88 return;
89 }
90 for (i = 0; i < ARRAY_SIZE(key_map); ++i)
91 if (key_map[i].key == key) {
92 form_driver(form, key_map[i].request);
93 break;
94 }
95 }
96
on_handle_key(int key)97 static void on_handle_key(int key)
98 {
99 switch (key) {
100 case 27:
101 case KEY_CANCEL:
102 form_widget.close();
103 break;
104 case 10:
105 case 13:
106 case KEY_ENTER:
107 on_key_enter();
108 break;
109 default:
110 on_form_key(key);
111 break;
112 }
113 }
114
create(void)115 static bool create(void)
116 {
117 const char *title;
118
119 if (screen_lines < 6 || screen_cols < 36) {
120 form_widget.close();
121 beep();
122 return FALSE;
123 }
124 widget_init(&form_widget,
125 6, 36, SCREEN_CENTER, SCREEN_CENTER,
126 attrs.textbox, WIDGET_BORDER | WIDGET_SUBWINDOW | WIDGET_CURSOR_VISIBLE);
127 title = _("Sound Card");
128 mvwprintw(form_widget.window, 0, (36 - 2 - get_mbs_width(title)) / 2, " %s ", title);
129
130 set_form_win(form, form_widget.window);
131 set_form_sub(form, form_widget.subwindow);
132 return TRUE;
133 }
134
on_window_size_changed(void)135 static void on_window_size_changed(void)
136 {
137 form_driver(form, REQ_VALIDATION); /* save field value */
138 unpost_form(form);
139
140 if (!create())
141 return;
142
143 /*
144 * This call fails because ncurses does not allow changing options of
145 * the current field, and we cannot change the current field because
146 * there is only one. The only way to make this work would be to throw
147 * away and recreate all fields.
148 */
149 field_opts_off(fields[1], O_BLANK);
150
151 post_form(form);
152 }
153
on_close(void)154 static void on_close(void)
155 {
156 unpost_form(form);
157 free_form(form);
158 free_field(fields[0]);
159 free_field(fields[1]);
160 widget_free(&form_widget);
161 }
162
163 static struct widget form_widget = {
164 .handle_key = on_handle_key,
165 .window_size_changed = on_window_size_changed,
166 .close = on_close,
167 };
168
create_device_name_form(void)169 void create_device_name_form(void)
170 {
171 fields[0] = new_field(1, 32, 1, 1, 0, 0);
172 if (!fields[0])
173 fatal_error("cannot create field");
174 field_opts_off(fields[0], O_ACTIVE|O_EDIT);
175 set_field_fore(fields[0], attrs.textbox);
176 set_field_back(fields[0], attrs.textbox);
177 set_field_buffer(fields[0], 0, _("Device name:"));
178
179 fields[1] = new_field(1, 32, 2, 1, 0, 0);
180 if (!fields[1])
181 fatal_error("cannot create field");
182 field_opts_off(fields[1], O_AUTOSKIP|O_NULLOK|O_STATIC);
183 set_field_fore(fields[1], attrs.textfield);
184 set_field_back(fields[1], attrs.textfield);
185 set_field_buffer(fields[1], 0, mixer_device_name);
186
187 form = new_form(fields);
188 if (!form)
189 fatal_error("cannot create form");
190
191 if (!create())
192 return;
193
194 post_form(form);
195 }
196