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