1/*****************************************************************************/
2// Expander
3// Written by Jérôme Duval
4//
5// ExpanderSettings.cpp
6//
7// Code from Diskprobe by Axel Dörfler
8//
9// Copyright (c) 2004 OpenBeOS Project
10//
11// Permission is hereby granted, free of charge, to any person obtaining a
12// copy of this software and associated documentation files (the "Software"),
13// to deal in the Software without restriction, including without limitation
14// the rights to use, copy, modify, merge, publish, distribute, sublicense,
15// and/or sell copies of the Software, and to permit persons to whom the
16// Software is furnished to do so, subject to the following conditions:
17//
18// The above copyright notice and this permission notice shall be included
19// in all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27// DEALINGS IN THE SOFTWARE.
28/*****************************************************************************/
29#include "ExpanderSettings.h"
30
31#include <ByteOrder.h>
32#include <Screen.h>
33#include <FindDirectory.h>
34#include <Entry.h>
35#include <stdlib.h>
36#include <string.h>
37#include <Path.h>
38
39//	Format of Expander_Settings
40//	1st byte :	unknown (0x1)
41//	2nd byte :	Automatically expand files (default : 0x0)
42//	3rd byte :	Close when done (default : 0x0)
43//	4th byte :	0x66
44//				0x63 (default)
45//				0x65
46//	5th byte : 	unknown (0x0)
47//	4 bytes : 	dev_t	(default : 0xffff)
48//	8 bytes : 	ino_t	(default : 0xfffffffff)
49//	4 bytes : 	name length (big endian) (default : 0x0)
50//	n bytes : 	name	(default : "")
51//	1 byte : 	Open destination folder (default : 0x1)
52//	1 byte : 	Show content listing (default : 0x0)
53//	4 bytes : 	window position topleft x (default : 0x4842)
54//	4 bytes : 	window position topleft y (default : 0x4842)
55
56
57template<typename T> bool
58read_data(BFile& file, T& value)
59{
60	return file.Read(&value, sizeof(T)) == (ssize_t)sizeof(T);
61}
62
63
64//	#pragma mark -
65
66
67ExpanderSettings::ExpanderSettings()
68	:
69	fMessage(kMsgExpanderSettings),
70	fUpdated(false)
71{
72	fMessage.AddBool("automatically_expand_files", false);
73	fMessage.AddBool("close_when_done", true);
74	fMessage.AddInt8("destination_folder", 0x63);
75	entry_ref ref;
76	fMessage.AddRef("destination_folder_use", &ref);
77	fMessage.AddBool("open_destination_folder", true);
78	fMessage.AddBool("show_contents_listing", false);
79	fMessage.AddPoint("window_position", BPoint(50, 50));
80
81	BFile file;
82	if (Open(&file, B_READ_ONLY) != B_OK)
83		return;
84
85	// TODO: load/save settings as flattened BMessage - but not yet,
86	//		since that will break compatibility with R5's Expander
87
88	bool unknown;
89	bool automaticallyExpandFiles;
90	bool closeWhenDone;
91	int8 destinationFolder;
92	bool openDestinationFolder;
93	bool showContentsListing;
94	BPoint position;
95	char name[B_FILE_NAME_LENGTH] = {'\0'};
96	int32 nameSize;
97	if (read_data(file, unknown)
98		&& read_data(file, automaticallyExpandFiles)
99		&& read_data(file, closeWhenDone)
100		&& read_data(file, destinationFolder)
101		&& read_data(file, unknown)
102		&& read_data(file, ref.device)
103		&& read_data(file, ref.directory)
104		&& read_data(file, nameSize)
105		&& (nameSize <= 0 || file.Read(name, nameSize) == nameSize)
106		&& read_data(file, openDestinationFolder)
107		&& read_data(file, showContentsListing)
108		&& read_data(file, position)) {
109		if (nameSize > 0 && nameSize < B_FILE_NAME_LENGTH) {
110			name[nameSize] = '\0';
111			ref.set_name(name);
112		}
113
114		// check if the window position is on screen at all
115		BScreen screen;
116		if (screen.Frame().Contains(position))
117			fMessage.ReplacePoint("window_position", position);
118
119		fMessage.ReplaceBool("automatically_expand_files",
120			automaticallyExpandFiles);
121		fMessage.ReplaceBool("close_when_done", closeWhenDone);
122		if (destinationFolder == 0x66
123			|| destinationFolder == 0x63
124			|| destinationFolder == 0x65)
125			fMessage.ReplaceInt8("destination_folder", destinationFolder);
126		BEntry entry(&ref);
127		if (entry.Exists())
128			fMessage.ReplaceRef("destination_folder_use", &ref);
129		fMessage.ReplaceBool("open_destination_folder", openDestinationFolder);
130		fMessage.ReplaceBool("show_contents_listing", showContentsListing);
131	}
132}
133
134
135ExpanderSettings::~ExpanderSettings()
136{
137	// only save the settings if something has changed
138	if (!fUpdated)
139		return;
140
141	BFile file;
142	if (Open(&file, B_CREATE_FILE | B_WRITE_ONLY) != B_OK)
143		return;
144
145	bool automaticallyExpandFiles;
146	bool closeWhenDone;
147	int8 destinationFolder;
148	entry_ref ref;
149	bool openDestinationFolder;
150	bool showContentsListing;
151	BPoint position;
152	bool unknown = 1;
153
154	if (fMessage.FindPoint("window_position", &position) == B_OK
155		&& fMessage.FindBool("automatically_expand_files",
156				&automaticallyExpandFiles) == B_OK
157		&& fMessage.FindBool("close_when_done", &closeWhenDone) == B_OK
158		&& fMessage.FindInt8("destination_folder", &destinationFolder) == B_OK
159		&& fMessage.FindRef("destination_folder_use", &ref) == B_OK
160		&& fMessage.FindBool("open_destination_folder",
161				&openDestinationFolder) == B_OK
162		&& fMessage.FindBool("show_contents_listing",
163			&showContentsListing) == B_OK) {
164		file.Write(&unknown, sizeof(unknown));
165		file.Write(&automaticallyExpandFiles, sizeof(automaticallyExpandFiles));
166		file.Write(&closeWhenDone, sizeof(closeWhenDone));
167		file.Write(&destinationFolder, sizeof(destinationFolder));
168		unknown = 0;
169		file.Write(&unknown, sizeof(unknown));
170		file.Write(&ref.device, sizeof(ref.device));
171		file.Write(&ref.directory, sizeof(ref.directory));
172		int32 nameSize = 0;
173		if (ref.name)
174			nameSize = strlen(ref.name);
175		file.Write(&nameSize, sizeof(nameSize));
176		file.Write(ref.name, nameSize);
177		file.Write(&openDestinationFolder, sizeof(openDestinationFolder));
178		file.Write(&showContentsListing, sizeof(showContentsListing));
179		file.Write(&position, sizeof(position));
180	}
181}
182
183
184status_t
185ExpanderSettings::Open(BFile *file, int32 mode)
186{
187	BPath path;
188	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
189		return B_ERROR;
190
191	path.Append("Expander_Settings");
192
193	return file->SetTo(path.Path(), mode);
194}
195
196
197void
198ExpanderSettings::UpdateFrom(BMessage *message)
199{
200	bool automaticallyExpandFiles;
201	bool closeWhenDone;
202	int8 destinationFolder;
203	entry_ref ref;
204	bool openDestinationFolder;
205	bool showContentsListing;
206	BPoint position;
207
208	if (message->FindPoint("window_position", &position) == B_OK)
209		fMessage.ReplacePoint("window_position", position);
210
211	if (message->FindBool("automatically_expand_files",
212			&automaticallyExpandFiles) == B_OK) {
213		fMessage.ReplaceBool("automatically_expand_files",
214			automaticallyExpandFiles);
215	}
216
217	if (message->FindBool("close_when_done", &closeWhenDone) == B_OK)
218		fMessage.ReplaceBool("close_when_done", closeWhenDone);
219
220	if (message->FindInt8("destination_folder", &destinationFolder) == B_OK)
221		fMessage.ReplaceInt8("destination_folder", destinationFolder);
222
223	if (message->FindRef("destination_folder_use", &ref) == B_OK)
224		fMessage.ReplaceRef("destination_folder_use", &ref);
225
226	if (message->FindBool("open_destination_folder",
227			&openDestinationFolder) == B_OK)
228		fMessage.ReplaceBool("open_destination_folder", openDestinationFolder);
229
230	if (message->FindBool("show_contents_listing",
231			&showContentsListing) == B_OK)
232		fMessage.ReplaceBool("show_contents_listing", showContentsListing);
233
234	fUpdated = true;
235}
236