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