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
34static struct widget form_widget;
35static FIELD *fields[3];
36static FORM *form;
37
38static 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
55static 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
69static 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
97static 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
115static 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
135static 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
154static 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
163static struct widget form_widget = {
164	.handle_key = on_handle_key,
165	.window_size_changed = on_window_size_changed,
166	.close = on_close,
167};
168
169void 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