1194612Sed/*
2194612Sed * Copyright 2008-2010, Stephan A��mus <superstippi@gmx.de>.
3194612Sed * Copyright 1998, Eric Shepherd.
4194612Sed * All rights reserved. Distributed under the terms of the Be Sample Code
5194612Sed * license.
6194612Sed */
7194612Sed
8194612Sed//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd)
9194612Sed
10194612Sed#include "SettingsMessage.h"
11194612Sed
12194612Sed#include <new>
13194612Sed
14194612Sed#include <Autolock.h>
15194612Sed#include <Entry.h>
16249423Sdim#include <File.h>
17249423Sdim#include <Messenger.h>
18249423Sdim#include <String.h>
19218893Sdim
20249423Sdim
21194612SedSettingsMessage::SettingsMessage(directory_which directory,
22194612Sed		const char* filename)
23218893Sdim	:
24194612Sed	BMessage('pref'),
25194612Sed	fListeners(0)
26249423Sdim{
27249423Sdim	fStatus = find_directory(directory, &fPath);
28198090Srdivacky
29198090Srdivacky	if (fStatus == B_OK)
30198090Srdivacky		fStatus = fPath.Append(filename);
31198090Srdivacky
32198090Srdivacky	if (fStatus == B_OK)
33198090Srdivacky		fStatus = Load();
34198090Srdivacky}
35198090Srdivacky
36198090Srdivacky
37198090SrdivackySettingsMessage::~SettingsMessage()
38198090Srdivacky{
39198090Srdivacky	Save();
40198090Srdivacky
41194612Sed	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
42198090Srdivacky		delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i));
43198090Srdivacky}
44198090Srdivacky
45203954Srdivacky
46194612Sedstatus_t
47194612SedSettingsMessage::InitCheck() const
48194612Sed{
49194612Sed	return fStatus;
50194612Sed}
51194612Sed
52194612Sed
53194612Sedstatus_t
54194612SedSettingsMessage::Load()
55263508Sdim{
56263508Sdim	BAutolock _(this);
57263508Sdim
58218893Sdim	BFile file(fPath.Path(), B_READ_ONLY);
59223017Sdim	status_t status = file.InitCheck();
60223017Sdim
61203954Srdivacky	if (status == B_OK)
62194612Sed		status = Unflatten(&file);
63194612Sed
64223017Sdim	return status;
65223017Sdim}
66194612Sed
67203954Srdivacky
68263508Sdimstatus_t
69194612SedSettingsMessage::Save() const
70218893Sdim{
71194612Sed	BAutolock _(const_cast<SettingsMessage*>(this));
72194612Sed
73194612Sed	BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
74194612Sed	status_t status = file.InitCheck();
75194612Sed
76194612Sed	if (status == B_OK)
77194612Sed		status = Flatten(&file);
78194612Sed
79194612Sed	return status;
80194612Sed}
81194612Sed
82194612Sed
83194612Sedbool
84194612SedSettingsMessage::AddListener(const BMessenger& listener)
85194612Sed{
86239462Sdim	BAutolock _(this);
87239462Sdim
88239462Sdim	BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener);
89239462Sdim	if (listenerCopy && fListeners.AddItem(listenerCopy))
90194612Sed		return true;
91194612Sed	delete listenerCopy;
92203954Srdivacky	return false;
93194612Sed}
94203954Srdivacky
95194612Sed
96194612Sedvoid
97194612SedSettingsMessage::RemoveListener(const BMessenger& listener)
98203954Srdivacky{
99239462Sdim	BAutolock _(this);
100239462Sdim
101194612Sed	for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
102198090Srdivacky		BMessenger* listenerItem = reinterpret_cast<BMessenger*>(
103198090Srdivacky			fListeners.ItemAtFast(i));
104198090Srdivacky		if (*listenerItem == listener) {
105198090Srdivacky			fListeners.RemoveItem(i);
106203954Srdivacky			delete listenerItem;
107198090Srdivacky			return;
108198090Srdivacky		}
109198090Srdivacky	}
110198090Srdivacky}
111198090Srdivacky
112198090Srdivacky
113198090Srdivacky// #pragma mark -
114194612Sed
115194612Sed
116203954Srdivackystatus_t
117198090SrdivackySettingsMessage::SetValue(const char* name, bool value)
118198090Srdivacky{
119198090Srdivacky	status_t ret = ReplaceBool(name, value);
120203954Srdivacky	if (ret != B_OK)
121198090Srdivacky		ret = AddBool(name, value);
122198090Srdivacky	if (ret == B_OK)
123198090Srdivacky		_NotifyValueChanged(name);
124198090Srdivacky	return ret;
125198090Srdivacky}
126239462Sdim
127239462Sdim
128239462Sdimstatus_t
129239462SdimSettingsMessage::SetValue(const char* name, int8 value)
130194612Sed{
131194612Sed	status_t ret = ReplaceInt8(name, value);
132195340Sed	if (ret != B_OK)
133194612Sed		ret = AddInt8(name, value);
134203954Srdivacky	if (ret == B_OK)
135194612Sed		_NotifyValueChanged(name);
136194612Sed	return ret;
137194612Sed}
138195340Sed
139203954Srdivacky
140195340Sedstatus_t
141195340SedSettingsMessage::SetValue(const char* name, int16 value)
142195340Sed{
143194612Sed	status_t ret = ReplaceInt16(name, value);
144194612Sed	if (ret != B_OK)
145194612Sed		ret = AddInt16(name, value);
146195340Sed	if (ret == B_OK)
147195340Sed		_NotifyValueChanged(name);
148195340Sed	return ret;
149195340Sed}
150195340Sed
151234353Sdim
152234353Sdimstatus_t
153249423SdimSettingsMessage::SetValue(const char* name, uint16 value)
154249423Sdim{
155203954Srdivacky	status_t ret = ReplaceUInt16(name, value);
156194612Sed	if (ret != B_OK)
157239462Sdim		ret = AddUInt16(name, value);
158239462Sdim	if (ret == B_OK)
159239462Sdim		_NotifyValueChanged(name);
160239462Sdim	return ret;
161239462Sdim}
162239462Sdim
163239462Sdim
164239462Sdimstatus_t
165239462SdimSettingsMessage::SetValue(const char* name, int32 value)
166203954Srdivacky{
167239462Sdim	status_t ret = ReplaceInt32(name, value);
168239462Sdim	if (ret != B_OK)
169239462Sdim		ret = AddInt32(name, value);
170239462Sdim	if (ret == B_OK)
171239462Sdim		_NotifyValueChanged(name);
172239462Sdim	return ret;
173239462Sdim}
174239462Sdim
175239462Sdim
176199989Srdivackystatus_t
177239462SdimSettingsMessage::SetValue(const char* name, uint32 value)
178239462Sdim{
179239462Sdim	status_t ret = ReplaceUInt32(name, value);
180239462Sdim	if (ret != B_OK)
181239462Sdim		ret = AddUInt32(name, value);
182239462Sdim	if (ret == B_BAD_TYPE && HasData(name, B_INT32_TYPE)) {
183199989Srdivacky		// For compatibility with older versions of this class, replace an int32
184239462Sdim		RemoveData(name);
185239462Sdim		ret = AddUInt32(name, value);
186239462Sdim	}
187239462Sdim	if (ret == B_OK)
188239462Sdim		_NotifyValueChanged(name);
189239462Sdim	return ret;
190239462Sdim}
191239462Sdim
192239462Sdim
193239462Sdimstatus_t
194239462SdimSettingsMessage::SetValue(const char* name, int64 value)
195239462Sdim{
196239462Sdim	status_t ret = ReplaceInt64(name, value);
197239462Sdim	if (ret != B_OK)
198239462Sdim		ret = AddInt64(name, value);
199239462Sdim	if (ret == B_OK)
200239462Sdim		_NotifyValueChanged(name);
201249423Sdim	return ret;
202239462Sdim}
203239462Sdim
204239462Sdim
205234353Sdimstatus_t
206239462SdimSettingsMessage::SetValue(const char* name, uint64 value)
207239462Sdim{
208234353Sdim	status_t ret = ReplaceUInt64(name, value);
209239462Sdim	if (ret != B_OK)
210239462Sdim		ret = AddUInt64(name, value);
211249423Sdim	if (ret == B_OK)
212194612Sed		_NotifyValueChanged(name);
213195340Sed	return ret;
214263508Sdim}
215263508Sdim
216234982Sdim
217249423Sdimstatus_t
218249423SdimSettingsMessage::SetValue(const char* name, float value)
219234353Sdim{
220206274Srdivacky	status_t ret = ReplaceFloat(name, value);
221206274Srdivacky	if (ret != B_OK)
222234353Sdim		ret = AddFloat(name, value);
223206274Srdivacky	if (ret == B_OK)
224206274Srdivacky		_NotifyValueChanged(name);
225218893Sdim	return ret;
226239462Sdim}
227239462Sdim
228239462Sdim
229239462Sdimstatus_t
230239462SdimSettingsMessage::SetValue(const char* name, double value)
231195340Sed{
232234982Sdim	status_t ret = ReplaceDouble(name, value);
233195340Sed	if (ret != B_OK)
234195340Sed		ret = AddDouble(name, value);
235263508Sdim	if (ret == B_OK)
236263508Sdim		_NotifyValueChanged(name);
237263508Sdim	return ret;
238263508Sdim}
239263508Sdim
240263508Sdim
241195340Sedstatus_t
242195340SedSettingsMessage::SetValue(const char* name, const char* value)
243195340Sed{
244195340Sed	status_t ret = ReplaceString(name, value);
245249423Sdim	if (ret != B_OK)
246234353Sdim		ret = AddString(name, value);
247249423Sdim	if (ret == B_OK)
248249423Sdim		_NotifyValueChanged(name);
249249423Sdim	return ret;
250234353Sdim}
251249423Sdim
252249423Sdim
253249423Sdimstatus_t
254234353SdimSettingsMessage::SetValue(const char* name, const BString& value)
255234353Sdim{
256249423Sdim	status_t ret = ReplaceString(name, value);
257249423Sdim	if (ret != B_OK)
258249423Sdim		ret = AddString(name, value);
259249423Sdim	if (ret == B_OK)
260234353Sdim		_NotifyValueChanged(name);
261249423Sdim	return ret;
262249423Sdim}
263249423Sdim
264249423Sdim
265249423Sdimstatus_t
266249423SdimSettingsMessage::SetValue(const char* name, const BPoint& value)
267249423Sdim{
268249423Sdim	status_t ret = ReplacePoint(name, value);
269249423Sdim	if (ret != B_OK)
270249423Sdim		ret = AddPoint(name, value);
271249423Sdim	if (ret == B_OK)
272249423Sdim		_NotifyValueChanged(name);
273249423Sdim	return ret;
274249423Sdim}
275249423Sdim
276249423Sdim
277249423Sdimstatus_t
278249423SdimSettingsMessage::SetValue(const char* name, const BRect& value)
279249423Sdim{
280249423Sdim	status_t ret = ReplaceRect(name, value);
281249423Sdim	if (ret != B_OK)
282249423Sdim		ret = AddRect(name, value);
283249423Sdim	if (ret == B_OK)
284249423Sdim		_NotifyValueChanged(name);
285249423Sdim	return ret;
286249423Sdim}
287249423Sdim
288249423Sdim
289249423Sdimstatus_t
290249423SdimSettingsMessage::SetValue(const char* name, const entry_ref& value)
291249423Sdim{
292249423Sdim	status_t ret = ReplaceRef(name, &value);
293249423Sdim	if (ret != B_OK)
294249423Sdim		ret = AddRef(name, &value);
295249423Sdim	if (ret == B_OK)
296249423Sdim		_NotifyValueChanged(name);
297249423Sdim	return ret;
298249423Sdim}
299249423Sdim
300249423Sdim
301249423Sdimstatus_t
302249423SdimSettingsMessage::SetValue(const char* name, const BMessage& value)
303249423Sdim{
304249423Sdim	status_t ret = ReplaceMessage(name, &value);
305249423Sdim	if (ret != B_OK)
306249423Sdim		ret = AddMessage(name, &value);
307249423Sdim	if (ret == B_OK)
308249423Sdim		_NotifyValueChanged(name);
309249423Sdim	return ret;
310249423Sdim}
311249423Sdim
312249423Sdim
313249423Sdimstatus_t
314249423SdimSettingsMessage::SetValue(const char* name, const BFlattenable* value)
315249423Sdim{
316249423Sdim	status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value));
317249423Sdim	if (ret != B_OK)
318249423Sdim		ret = AddFlat(name, const_cast<BFlattenable*>(value));
319249423Sdim	if (ret == B_OK)
320249423Sdim		_NotifyValueChanged(name);
321249423Sdim	return ret;
322249423Sdim}
323249423Sdim
324249423Sdim
325249423Sdimstatus_t
326249423SdimSettingsMessage::SetValue(const char* name, type_code type, const void* data,
327249423Sdim	ssize_t numBytes)
328249423Sdim{
329249423Sdim	status_t ret = ReplaceData(name, type, data, numBytes);
330249423Sdim	if (ret != B_OK)
331249423Sdim		ret = AddData(name, type, data, numBytes);
332249423Sdim	if (ret == B_OK)
333249423Sdim		_NotifyValueChanged(name);
334249423Sdim	return ret;
335249423Sdim}
336249423Sdim
337249423Sdim
338249423Sdimstatus_t
339249423SdimSettingsMessage::SetValue(const char* name, const BFont& value)
340249423Sdim{
341249423Sdim	font_family family;
342249423Sdim	font_style style;
343249423Sdim	value.GetFamilyAndStyle(&family, &style);
344249423Sdim
345249423Sdim	BMessage fontMessage;
346249423Sdim	status_t ret = fontMessage.AddString("family", family);
347249423Sdim	if (ret == B_OK)
348234982Sdim		ret = fontMessage.AddString("style", style);
349234982Sdim	if (ret == B_OK)
350239462Sdim		ret = fontMessage.AddFloat("size", value.Size());
351239462Sdim
352234982Sdim	if (ret == B_OK) {
353234982Sdim		if (ReplaceMessage(name, &fontMessage) != B_OK)
354234982Sdim			ret = AddMessage(name, &fontMessage);
355234982Sdim	}
356195340Sed	if (ret == B_OK)
357195340Sed		_NotifyValueChanged(name);
358195340Sed	return ret;
359202878Srdivacky}
360202878Srdivacky
361202878Srdivacky
362202878Srdivacky// #pragma mark -
363202878Srdivacky
364203954Srdivacky
365202878Srdivackybool
366202878SrdivackySettingsMessage::GetValue(const char* name, bool defaultValue) const
367202878Srdivacky{
368202878Srdivacky	bool value;
369202878Srdivacky	if (FindBool(name, &value) != B_OK)
370202878Srdivacky		return defaultValue;
371195340Sed	return value;
372203954Srdivacky}
373234353Sdim
374234982Sdim
375234982Sdimint8
376234982SdimSettingsMessage::GetValue(const char* name, int8 defaultValue) const
377234982Sdim{
378234982Sdim	int8 value;
379234982Sdim	if (FindInt8(name, &value) != B_OK)
380234982Sdim		return defaultValue;
381234982Sdim	return value;
382234982Sdim}
383234982Sdim
384234982Sdim
385234982Sdimint16
386234982SdimSettingsMessage::GetValue(const char* name, int16 defaultValue) const
387234982Sdim{
388234982Sdim	int16 value;
389234353Sdim	if (FindInt16(name, &value) != B_OK)
390234982Sdim		return defaultValue;
391234982Sdim	return value;
392234982Sdim}
393234982Sdim
394234982Sdim
395234982Sdimuint16
396202878SrdivackySettingsMessage::GetValue(const char* name, uint16 defaultValue) const
397199989Srdivacky{
398234982Sdim	uint16 value;
399234982Sdim	if (FindUInt16(name, &value) != B_OK)
400234982Sdim		return defaultValue;
401234353Sdim	return value;
402234353Sdim}
403203954Srdivacky
404249423Sdim
405249423Sdimint32
406249423SdimSettingsMessage::GetValue(const char* name, int32 defaultValue) const
407249423Sdim{
408249423Sdim	int32 value;
409249423Sdim	if (FindInt32(name, &value) != B_OK)
410249423Sdim		return defaultValue;
411249423Sdim	return value;
412249423Sdim}
413249423Sdim
414249423Sdim
415249423Sdimuint32
416234353SdimSettingsMessage::GetValue(const char* name, uint32 defaultValue) const
417249423Sdim{
418234353Sdim	uint32 value;
419234353Sdim	if (FindUInt32(name, &value) == B_OK)
420234353Sdim		return value;
421234353Sdim	// For compatibility with older versions of this class, also accept an int32
422249423Sdim	int32 signedValue;
423249423Sdim	if (FindInt32(name, &signedValue) == B_OK && signedValue >= 0)
424249423Sdim		return signedValue;
425195340Sed	return defaultValue;
426249423Sdim}
427249423Sdim
428249423Sdim
429249423Sdimint64
430249423SdimSettingsMessage::GetValue(const char* name, int64 defaultValue) const
431249423Sdim{
432249423Sdim	int64 value;
433249423Sdim	if (FindInt64(name, &value) != B_OK)
434234353Sdim		return defaultValue;
435249423Sdim	return value;
436234353Sdim}
437234353Sdim
438249423Sdim
439234353Sdimuint64
440234353SdimSettingsMessage::GetValue(const char* name, uint64 defaultValue) const
441234353Sdim{
442234353Sdim	uint64 value;
443234353Sdim	if (FindUInt64(name, &value) != B_OK)
444234353Sdim		return defaultValue;
445249423Sdim	return value;
446234353Sdim}
447234982Sdim
448234982Sdim
449234982Sdimfloat
450234353SdimSettingsMessage::GetValue(const char* name, float defaultValue) const
451234353Sdim{
452234353Sdim	float value;
453234353Sdim	if (FindFloat(name, &value) != B_OK)
454234353Sdim		return defaultValue;
455234353Sdim	return value;
456234353Sdim}
457234353Sdim
458234353Sdim
459234353Sdimdouble
460234353SdimSettingsMessage::GetValue(const char* name, double defaultValue) const
461234353Sdim{
462249423Sdim	double value;
463234353Sdim	if (FindDouble(name, &value) != B_OK)
464249423Sdim		return defaultValue;
465234982Sdim	return value;
466234982Sdim}
467234982Sdim
468249423Sdim
469249423SdimBString
470249423SdimSettingsMessage::GetValue(const char* name, const BString& defaultValue) const
471249423Sdim{
472234353Sdim	BString value;
473263508Sdim	if (FindString(name, &value) != B_OK)
474249423Sdim		return defaultValue;
475249423Sdim	return value;
476249423Sdim}
477249423Sdim
478249423Sdim
479249423Sdimconst char*
480249423SdimSettingsMessage::GetValue(const char* name, const char* defaultValue) const
481249423Sdim{
482249423Sdim	const char* value;
483249423Sdim	if (FindString(name, &value) != B_OK)
484249423Sdim		return defaultValue;
485249423Sdim	return value;
486249423Sdim}
487249423Sdim
488249423Sdim
489249423SdimBPoint
490249423SdimSettingsMessage::GetValue(const char *name, BPoint defaultValue) const
491249423Sdim{
492249423Sdim	BPoint value;
493234353Sdim	if (FindPoint(name, &value) != B_OK)
494195340Sed		return defaultValue;
495	return value;
496}
497
498
499BRect
500SettingsMessage::GetValue(const char* name, BRect defaultValue) const
501{
502	BRect value;
503	if (FindRect(name, &value) != B_OK)
504		return defaultValue;
505	return value;
506}
507
508
509entry_ref
510SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const
511{
512	entry_ref value;
513	if (FindRef(name, &value) != B_OK)
514		return defaultValue;
515	return value;
516}
517
518
519BMessage
520SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const
521{
522	BMessage value;
523	if (FindMessage(name, &value) != B_OK)
524		return defaultValue;
525	return value;
526}
527
528
529BFont
530SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const
531{
532	BMessage fontMessage;
533	if (FindMessage(name, &fontMessage) != B_OK)
534		return defaultValue;
535
536	const char* family;
537	const char* style;
538	float size;
539	if (fontMessage.FindString("family", &family) != B_OK
540		|| fontMessage.FindString("style", &style) != B_OK
541		|| fontMessage.FindFloat("size", &size) != B_OK) {
542		return defaultValue;
543	}
544
545	BFont value;
546	if (value.SetFamilyAndStyle(family, style) != B_OK)
547		return defaultValue;
548
549	value.SetSize(size);
550
551	return value;
552}
553
554
555void*
556SettingsMessage::GetValue(const char* name, type_code type, ssize_t numBytes,
557		const void** defaultValue) const
558{
559	void* value;
560	if (FindData(name, type, (const void**)&value, &numBytes) != B_OK)
561		return defaultValue;
562	return value;
563}
564
565
566// #pragma mark - private
567
568void
569SettingsMessage::_NotifyValueChanged(const char* name) const
570{
571	BMessage message(SETTINGS_VALUE_CHANGED);
572	message.AddString("name", name);
573
574	// Add the value of that name to the notification.
575	type_code type;
576	if (GetInfo(name, &type) == B_OK) {
577		const void* data;
578		ssize_t numBytes;
579		if (FindData(name, type, &data, &numBytes) == B_OK)
580			message.AddData("value", type, data, numBytes);
581	}
582
583	int32 count = fListeners.CountItems();
584	for (int32 i = 0; i < count; i++) {
585		BMessenger* listener = reinterpret_cast<BMessenger*>(
586			fListeners.ItemAtFast(i));
587		listener->SendMessage(&message);
588	}
589}
590