xref: /haiku/src/apps/expander/ExpanderSettings.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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 Haiku 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 
30 
31 #include "ExpanderSettings.h"
32 
33 #include <ByteOrder.h>
34 #include <Directory.h>
35 #include <Screen.h>
36 #include <FindDirectory.h>
37 #include <Entry.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <Path.h>
41 
42 
43 //	Format of Expander_Settings
44 //	1st byte :	unknown (0x1)
45 //	2nd byte :	Automatically expand files (default : 0x0)
46 //	3rd byte :	Close when done (default : 0x0)
47 //	4th byte :	0x66
48 //				0x63 (default)
49 //				0x65
50 //	5th byte : 	unknown (0x0)
51 //	4 bytes : 	dev_t	(default : 0xffff)
52 //	8 bytes : 	ino_t	(default : 0xfffffffff)
53 //	4 bytes : 	name length (big endian) (default : 0x0)
54 //	n bytes : 	name	(default : "")
55 //	1 byte : 	Open destination folder (default : 0x1)
56 //	1 byte : 	Show content listing (default : 0x0)
57 //	4 bytes : 	window position topleft x (default : 0x4842)
58 //	4 bytes : 	window position topleft y (default : 0x4842)
59 
60 
61 template<typename T> bool
62 read_data(BFile& file, T& value)
63 {
64 	return file.Read(&value, sizeof(T)) == (ssize_t)sizeof(T);
65 }
66 
67 
68 //	#pragma mark - ExpanderSettings
69 
70 
71 ExpanderSettings::ExpanderSettings()
72 	:
73 	fMessage(kMsgExpanderSettings),
74 	fUpdated(false)
75 {
76 	fMessage.AddBool("automatically_expand_files", false);
77 	fMessage.AddBool("close_when_done", true);
78 	fMessage.AddInt8("destination_folder", 0x63);
79 	entry_ref ref;
80 	fMessage.AddRef("destination_folder_use", &ref);
81 	fMessage.AddBool("open_destination_folder", true);
82 	fMessage.AddBool("show_contents_listing", false);
83 	fMessage.AddPoint("window_position", BPoint(50, 50));
84 
85 	BFile file;
86 	if (Open(&file, B_READ_ONLY) != B_OK)
87 		return;
88 
89 	// TODO: load/save settings as flattened BMessage - but not yet,
90 	//       since that will break compatibility with R5's Expander
91 
92 	bool unknown;
93 	bool automaticallyExpandFiles;
94 	bool closeWhenDone;
95 	int8 destinationFolder;
96 	bool openDestinationFolder;
97 	bool showContentsListing;
98 	BPoint position;
99 	char name[B_FILE_NAME_LENGTH] = {'\0'};
100 	int32 nameSize;
101 	if (read_data(file, unknown)
102 		&& read_data(file, automaticallyExpandFiles)
103 		&& read_data(file, closeWhenDone)
104 		&& read_data(file, destinationFolder)
105 		&& read_data(file, unknown)
106 		&& read_data(file, ref.device)
107 		&& read_data(file, ref.directory)
108 		&& read_data(file, nameSize)
109 		&& (nameSize <= 0 || file.Read(name, nameSize) == nameSize)
110 		&& read_data(file, openDestinationFolder)
111 		&& read_data(file, showContentsListing)
112 		&& read_data(file, position)) {
113 		if (nameSize > 0 && nameSize < B_FILE_NAME_LENGTH) {
114 			name[nameSize] = '\0';
115 			ref.set_name(name);
116 		}
117 
118 		// check if the window position is on screen at all
119 		BScreen screen;
120 		if (screen.Frame().Contains(position))
121 			fMessage.ReplacePoint("window_position", position);
122 
123 		fMessage.ReplaceBool("automatically_expand_files",
124 			automaticallyExpandFiles);
125 		fMessage.ReplaceBool("close_when_done", closeWhenDone);
126 		if (destinationFolder == 0x66
127 			|| destinationFolder == 0x63
128 			|| destinationFolder == 0x65) {
129 			fMessage.ReplaceInt8("destination_folder", destinationFolder);
130 		}
131 
132 		BEntry entry(&ref);
133 		if (entry.Exists())
134 			fMessage.ReplaceRef("destination_folder_use", &ref);
135 
136 		fMessage.ReplaceBool("open_destination_folder", openDestinationFolder);
137 		fMessage.ReplaceBool("show_contents_listing", showContentsListing);
138 	}
139 }
140 
141 
142 ExpanderSettings::~ExpanderSettings()
143 {
144 	// only save the settings if something has changed
145 	if (!fUpdated)
146 		return;
147 
148 	BFile file;
149 	if (Open(&file, B_CREATE_FILE | B_WRITE_ONLY) != B_OK)
150 		return;
151 
152 	bool automaticallyExpandFiles;
153 	bool closeWhenDone;
154 	int8 destinationFolder;
155 	entry_ref ref;
156 	bool openDestinationFolder;
157 	bool showContentsListing;
158 	BPoint position;
159 	bool unknown = 1;
160 
161 	if (fMessage.FindPoint("window_position", &position) == B_OK
162 		&& fMessage.FindBool("automatically_expand_files",
163 			&automaticallyExpandFiles) == B_OK
164 		&& fMessage.FindBool("close_when_done", &closeWhenDone) == B_OK
165 		&& fMessage.FindInt8("destination_folder", &destinationFolder) == B_OK
166 		&& fMessage.FindRef("destination_folder_use", &ref) == B_OK
167 		&& fMessage.FindBool("open_destination_folder",
168 			&openDestinationFolder) == B_OK
169 		&& fMessage.FindBool("show_contents_listing",
170 			&showContentsListing) == B_OK) {
171 		file.Write(&unknown, sizeof(unknown));
172 		file.Write(&automaticallyExpandFiles, sizeof(automaticallyExpandFiles));
173 		file.Write(&closeWhenDone, sizeof(closeWhenDone));
174 		file.Write(&destinationFolder, sizeof(destinationFolder));
175 		unknown = 0;
176 		file.Write(&unknown, sizeof(unknown));
177 		file.Write(&ref.device, sizeof(ref.device));
178 		file.Write(&ref.directory, sizeof(ref.directory));
179 		int32 nameSize = 0;
180 		if (ref.name)
181 			nameSize = strlen(ref.name);
182 
183 		file.Write(&nameSize, sizeof(nameSize));
184 		file.Write(ref.name, nameSize);
185 		file.Write(&openDestinationFolder, sizeof(openDestinationFolder));
186 		file.Write(&showContentsListing, sizeof(showContentsListing));
187 		file.Write(&position, sizeof(position));
188 	}
189 }
190 
191 
192 /*static*/ status_t
193 ExpanderSettings::GetSettingsDirectoryPath(BPath& _path)
194 {
195 	status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &_path);
196 	return error == B_OK ? _path.Append("expander") : error;
197 }
198 
199 
200 status_t
201 ExpanderSettings::Open(BFile* file, int32 mode)
202 {
203 	BPath path;
204 	status_t error = GetSettingsDirectoryPath(path);
205 	if (error != B_OK)
206 		return error;
207 
208 	// create the directory, if file creation is requested
209 	if ((mode & B_CREATE_FILE) != 0) {
210 		error = create_directory(path.Path(), 0755);
211 		if (error != B_OK)
212 			return error;
213 	}
214 
215 	error = path.Append("settings");
216 	if (error != B_OK)
217 		return error;
218 
219 	return file->SetTo(path.Path(), mode);
220 }
221 
222 
223 void
224 ExpanderSettings::UpdateFrom(BMessage* message)
225 {
226 	bool automaticallyExpandFiles;
227 	bool closeWhenDone;
228 	int8 destinationFolder;
229 	entry_ref ref;
230 	bool openDestinationFolder;
231 	bool showContentsListing;
232 	BPoint position;
233 
234 	if (message->FindPoint("window_position", &position) == B_OK)
235 		fMessage.ReplacePoint("window_position", position);
236 
237 	if (message->FindBool("automatically_expand_files",
238 			&automaticallyExpandFiles) == B_OK) {
239 		fMessage.ReplaceBool("automatically_expand_files",
240 			automaticallyExpandFiles);
241 	}
242 
243 	if (message->FindBool("close_when_done", &closeWhenDone) == B_OK)
244 		fMessage.ReplaceBool("close_when_done", closeWhenDone);
245 
246 	if (message->FindInt8("destination_folder", &destinationFolder) == B_OK)
247 		fMessage.ReplaceInt8("destination_folder", destinationFolder);
248 
249 	if (message->FindRef("destination_folder_use", &ref) == B_OK)
250 		fMessage.ReplaceRef("destination_folder_use", &ref);
251 
252 	if (message->FindBool("open_destination_folder",
253 			&openDestinationFolder) == B_OK)
254 		fMessage.ReplaceBool("open_destination_folder", openDestinationFolder);
255 
256 	if (message->FindBool("show_contents_listing",
257 			&showContentsListing) == B_OK) {
258 		fMessage.ReplaceBool("show_contents_listing", showContentsListing);
259 	}
260 
261 	fUpdated = true;
262 }
263