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