1/* -----------------------------------------------------------------------
2 * Copyright (c) 2004 Waldemar Kornewald, Waldemar.Kornewald@web.de
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 * ----------------------------------------------------------------------- */
22
23#include "MessageDriverSettingsUtils.h"
24
25#include <PPPDefs.h>
26#include <settings_tools.h>
27#include <File.h>
28#include <Message.h>
29#include <String.h>
30
31#include <cstdio>
32
33
34static bool AddParameters(const BMessage& message, driver_settings *to);
35
36
37bool
38FindMessageParameter(const char *name, const BMessage& message, BMessage *save,
39	int32 *startIndex)
40{
41	// XXX: this should be removed when we can replace BMessage with something better
42	BString string;
43	int32 index = startIndex ? *startIndex : 0;
44	for(; message.FindMessage(MDSU_PARAMETERS, index, save) == B_OK; index++) {
45		if(save->FindString(MDSU_NAME, &string) == B_OK
46				&& string.ICompare(name) == 0) {
47			if(startIndex)
48				*startIndex = index;
49			return true;
50		}
51	}
52
53	return false;
54}
55
56
57static
58bool
59AddValues(const BMessage& message, driver_parameter *parameter)
60{
61	const char *value;
62	for(int32 index = 0; message.FindString(MDSU_VALUES, index, &value) == B_OK;
63			index++)
64		if(!add_driver_parameter_value(value, parameter))
65			return false;
66
67	return true;
68}
69
70
71inline
72bool
73AddParameters(const BMessage& message, driver_parameter *to)
74{
75	if(!to)
76		return false;
77
78	return AddParameters(message,
79		reinterpret_cast<driver_settings*>(&to->parameter_count));
80}
81
82
83static
84bool
85AddParameters(const BMessage& message, driver_settings *to)
86{
87	const char *name;
88	BMessage current;
89	driver_parameter *parameter;
90	for(int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index,
91			&current) == B_OK; index++) {
92		name = current.FindString(MDSU_NAME);
93		parameter = new_driver_parameter(name);
94		if(!AddValues(current, parameter))
95			return false;
96
97		AddParameters(current, parameter);
98		add_driver_parameter(parameter, to);
99	}
100
101	return true;
102}
103
104
105driver_settings*
106MessageToDriverSettings(const BMessage& message)
107{
108	driver_settings *settings = new_driver_settings();
109
110	if(!AddParameters(message, settings)) {
111		free_driver_settings(settings);
112		return NULL;
113	}
114
115	return settings;
116}
117
118
119static
120bool
121AddParameter(const driver_parameter *parameter, BMessage *message)
122{
123	if(!parameter || !message)
124		return false;
125
126	if(parameter->name)
127		message->AddString(MDSU_NAME, parameter->name);
128	else
129		return false;
130
131	for(int32 index = 0; index < parameter->value_count; index++)
132		if(parameter->values[index])
133			message->AddString(MDSU_VALUES, parameter->values[index]);
134
135	for(int32 index = 0; index < parameter->parameter_count; index++) {
136		BMessage parameterMessage;
137		AddParameter(&parameter->parameters[index], &parameterMessage);
138		message->AddMessage(MDSU_PARAMETERS, &parameterMessage);
139	}
140
141	return true;
142}
143
144
145bool
146ReadMessageDriverSettings(const char *name, BMessage *message)
147{
148	if(!name || !message)
149		return false;
150
151	void *handle = load_driver_settings(name);
152	if(!handle)
153		return false;
154	const driver_settings *settings = get_driver_settings(handle);
155	if(!settings) {
156		unload_driver_settings(handle);
157		return false;
158	}
159
160	for(int32 index = 0; index < settings->parameter_count; index++) {
161		BMessage parameter;
162		AddParameter(&settings->parameters[index], &parameter);
163		message->AddMessage(MDSU_PARAMETERS, &parameter);
164	}
165
166	unload_driver_settings(handle);
167
168	return true;
169}
170
171
172static
173void
174EscapeWord(BString& word)
175{
176	word.ReplaceAll("\\", "\\\\");
177	word.ReplaceAll("#", "\\#");
178	word.ReplaceAll("\"", "\\\"");
179	word.ReplaceAll("\'", "\\\'");
180}
181
182
183static
184bool
185WriteParameter(BFile& file, const BMessage& parameter, int32 level)
186{
187	const char *name;
188	if(parameter.FindString(MDSU_NAME, &name) != B_OK || !name)
189		return false;
190
191	BString line, word(name);
192	EscapeWord(word);
193	bool needsEscaping = word.FindFirst(' ') >= 0;
194	line.SetTo('\t', level);
195	if(needsEscaping)
196		line << '\"';
197	line << word;
198	if(needsEscaping)
199		line << '\"';
200
201	for(int32 index = 0; parameter.FindString(MDSU_VALUES, index, &name) == B_OK;
202			index++)
203		if(name) {
204			line << ' ';
205			word = name;
206			EscapeWord(word);
207			needsEscaping = word.FindFirst(' ') >= 0;
208			if(needsEscaping)
209				line << '\"';
210			line << word;
211			if(needsEscaping)
212				line << '\"';
213		}
214
215	type_code type;
216	int32 parameterCount;
217	parameter.GetInfo(MDSU_PARAMETERS, &type, &parameterCount);
218
219	if(parameterCount > 0)
220		line << " {";
221
222	line << '\n';
223	file.Write(line.String(), line.Length());
224
225	if(parameterCount > 0) {
226		BMessage subParameter;
227		for(int32 index = 0; parameter.FindMessage(MDSU_PARAMETERS, index,
228				&subParameter) == B_OK; index++)
229			WriteParameter(file, subParameter, level + 1);
230
231		line.SetTo('\t', level);
232		line << "}\n";
233		file.Write(line.String(), line.Length());
234	}
235
236	return true;
237}
238
239
240bool
241WriteMessageDriverSettings(BFile& file, const BMessage& message)
242{
243	if(file.InitCheck() != B_OK || !file.IsWritable())
244		return false;
245
246	file.SetSize(0);
247	file.Seek(0, SEEK_SET);
248
249	BMessage parameter;
250	for(int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index, &parameter) == B_OK;
251			index++) {
252		if(index > 0)
253			file.Write("\n", 1);
254		WriteParameter(file, parameter, 0);
255	}
256
257	return true;
258}
259