1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 #include <Debug.h> 36 #include <AppDefs.h> 37 #include <InterfaceDefs.h> 38 39 #include "Attributes.h" 40 #include "Commands.h" 41 #include "PoseView.h" 42 #include "Utilities.h" 43 #include "ViewState.h" 44 45 #include <new> 46 #include <string.h> 47 #include <stdlib.h> 48 49 50 const char *kColumnVersionName = "BColumn:version"; 51 const char *kColumnTitleName = "BColumn:fTitle"; 52 const char *kColumnOffsetName = "BColumn:fOffset"; 53 const char *kColumnWidthName = "BColumn:fWidth"; 54 const char *kColumnAlignmentName = "BColumn:fAlignment"; 55 const char *kColumnAttrName = "BColumn:fAttrName"; 56 const char *kColumnAttrHashName = "BColumn:fAttrHash"; 57 const char *kColumnAttrTypeName = "BColumn:fAttrType"; 58 const char *kColumnDisplayAsName = "BColumn:fDisplayAs"; 59 const char *kColumnStatFieldName = "BColumn:fStatField"; 60 const char *kColumnEditableName = "BColumn:fEditable"; 61 62 const char *kViewStateVersionName = "ViewState:version"; 63 const char *kViewStateViewModeName = "ViewState:fViewMode"; 64 const char *kViewStateLastIconModeName = "ViewState:fLastIconMode"; 65 const char *kViewStateListOriginName = "ViewState:fListOrigin"; 66 const char *kViewStateIconOriginName = "ViewState:fIconOrigin"; 67 const char *kViewStatePrimarySortAttrName = "ViewState:fPrimarySortAttr"; 68 const char *kViewStatePrimarySortTypeName = "ViewState:fPrimarySortType"; 69 const char *kViewStateSecondarySortAttrName = "ViewState:fSecondarySortAttr"; 70 const char *kViewStateSecondarySortTypeName = "ViewState:fSecondarySortType"; 71 const char *kViewStateReverseSortName = "ViewState:fReverseSort"; 72 const char *kViewStateIconSizeName = "ViewState:fIconSize"; 73 74 75 static const int32 kColumnStateMinArchiveVersion = 21; 76 // bump version when layout changes 77 78 79 BColumn::BColumn(const char *title, float offset, float width, 80 alignment align, const char *attributeName, uint32 attrType, 81 const char* displayAs, bool statField, bool editable) 82 { 83 _Init(title, offset, width, align, attributeName, attrType, displayAs, 84 statField, editable); 85 } 86 87 88 BColumn::BColumn(const char *title, float offset, float width, 89 alignment align, const char *attributeName, uint32 attrType, 90 bool statField, bool editable) 91 { 92 _Init(title, offset, width, align, attributeName, attrType, NULL, 93 statField, editable); 94 } 95 96 97 BColumn::~BColumn() 98 { 99 } 100 101 102 BColumn::BColumn(BMallocIO *stream, int32 version, bool endianSwap) 103 { 104 StringFromStream(&fTitle, stream, endianSwap); 105 stream->Read(&fOffset, sizeof(float)); 106 stream->Read(&fWidth, sizeof(float)); 107 stream->Read(&fAlignment, sizeof(alignment)); 108 StringFromStream(&fAttrName, stream, endianSwap); 109 stream->Read(&fAttrHash, sizeof(uint32)); 110 stream->Read(&fAttrType, sizeof(uint32)); 111 stream->Read(&fStatField, sizeof(bool)); 112 stream->Read(&fEditable, sizeof(bool)); 113 if (version == kColumnStateArchiveVersion) 114 StringFromStream(&fDisplayAs, stream, endianSwap); 115 116 if (endianSwap) { 117 PRINT(("endian swapping column\n")); 118 fOffset = B_SWAP_FLOAT(fOffset); 119 fWidth = B_SWAP_FLOAT(fWidth); 120 STATIC_ASSERT(sizeof(BColumn::fAlignment) == sizeof(int32)); 121 fAlignment = (alignment)B_SWAP_INT32(fAlignment); 122 fAttrHash = B_SWAP_INT32(fAttrHash); 123 fAttrType = B_SWAP_INT32(fAttrType); 124 } 125 } 126 127 128 BColumn::BColumn(const BMessage &message, int32 index) 129 { 130 message.FindString(kColumnTitleName, index, &fTitle); 131 message.FindFloat(kColumnOffsetName, index, &fOffset); 132 message.FindFloat(kColumnWidthName, index, &fWidth); 133 message.FindInt32(kColumnAlignmentName, index, (int32 *)&fAlignment); 134 message.FindString(kColumnAttrName, index, &fAttrName); 135 message.FindInt32(kColumnAttrHashName, index, (int32 *)&fAttrHash); 136 message.FindInt32(kColumnAttrTypeName, index, (int32 *)&fAttrType); 137 message.FindString(kColumnDisplayAsName, index, &fDisplayAs); 138 message.FindBool(kColumnStatFieldName, index, &fStatField); 139 message.FindBool(kColumnEditableName, index, &fEditable); 140 } 141 142 143 void 144 BColumn::_Init(const char *title, float offset, float width, 145 alignment align, const char *attributeName, uint32 attrType, 146 const char* displayAs, bool statField, bool editable) 147 { 148 fTitle = title; 149 fAttrName = attributeName; 150 fDisplayAs = displayAs; 151 fOffset = offset; 152 fWidth = width; 153 fAlignment = align; 154 fAttrHash = AttrHashString(attributeName, attrType); 155 fAttrType = attrType; 156 fStatField = statField; 157 fEditable = editable; 158 } 159 160 161 BColumn * 162 BColumn::InstantiateFromStream(BMallocIO *stream, bool endianSwap) 163 { 164 // compare stream header in canonical form 165 166 // we can't use ValidateStream(), as we preserve backwards compatibility 167 int32 version; 168 uint32 key; 169 if (stream->Read(&key, sizeof(uint32)) <= 0 170 || stream->Read(&version, sizeof(int32)) <=0) 171 return 0; 172 173 if (endianSwap) { 174 key = SwapUInt32(key); 175 version = SwapInt32(version); 176 } 177 178 if (key != AttrHashString("BColumn", B_OBJECT_TYPE) 179 || version < kColumnStateMinArchiveVersion) 180 return 0; 181 182 // PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : "")); 183 return _Sanitize(new (std::nothrow) BColumn(stream, version, endianSwap)); 184 } 185 186 187 BColumn * 188 BColumn::InstantiateFromMessage(const BMessage &message, int32 index) 189 { 190 int32 version = kColumnStateArchiveVersion; 191 int32 messageVersion; 192 193 if (message.FindInt32(kColumnVersionName, index, &messageVersion) != B_OK) 194 return NULL; 195 196 if (version != messageVersion) 197 return NULL; 198 199 return _Sanitize(new (std::nothrow) BColumn(message, index)); 200 } 201 202 203 void 204 BColumn::ArchiveToStream(BMallocIO *stream) const 205 { 206 // write class identifier and version info 207 uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE); 208 stream->Write(&key, sizeof(uint32)); 209 int32 version = kColumnStateArchiveVersion; 210 stream->Write(&version, sizeof(int32)); 211 212 // PRINT(("ArchiveToStream column, key %x, version %d\n", key, version)); 213 214 StringToStream(&fTitle, stream); 215 stream->Write(&fOffset, sizeof(float)); 216 stream->Write(&fWidth, sizeof(float)); 217 stream->Write(&fAlignment, sizeof(alignment)); 218 StringToStream(&fAttrName, stream); 219 stream->Write(&fAttrHash, sizeof(uint32)); 220 stream->Write(&fAttrType, sizeof(uint32)); 221 stream->Write(&fStatField, sizeof(bool)); 222 stream->Write(&fEditable, sizeof(bool)); 223 StringToStream(&fDisplayAs, stream); 224 } 225 226 227 void 228 BColumn::ArchiveToMessage(BMessage &message) const 229 { 230 message.AddInt32(kColumnVersionName, kColumnStateArchiveVersion); 231 232 message.AddString(kColumnTitleName, fTitle); 233 message.AddFloat(kColumnOffsetName, fOffset); 234 message.AddFloat(kColumnWidthName, fWidth); 235 message.AddInt32(kColumnAlignmentName, fAlignment); 236 message.AddString(kColumnAttrName, fAttrName); 237 message.AddInt32(kColumnAttrHashName, static_cast<int32>(fAttrHash)); 238 message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType)); 239 if (fDisplayAs.Length() > 0) 240 message.AddString(kColumnDisplayAsName, fDisplayAs.String()); 241 message.AddBool(kColumnStatFieldName, fStatField); 242 message.AddBool(kColumnEditableName, fEditable); 243 } 244 245 246 BColumn * 247 BColumn::_Sanitize(BColumn *column) 248 { 249 if (column == NULL) 250 return NULL; 251 252 // sanity-check the resulting column 253 if (column->fTitle.Length() > 500 254 || column->fOffset < 0 255 || column->fOffset > 10000 256 || column->fWidth < 0 257 || column->fWidth > 10000 258 || (int32)column->fAlignment < B_ALIGN_LEFT 259 || (int32)column->fAlignment > B_ALIGN_CENTER 260 || column->fAttrName.Length() > 500) { 261 PRINT(("column data not valid\n")); 262 delete column; 263 return NULL; 264 } 265 #if DEBUG 266 // TODO: Whatever this is supposed to mean, fix it. 267 // else if (endianSwap) 268 // PRINT(("Instantiated foreign column ok\n")); 269 #endif 270 271 return column; 272 } 273 274 275 // #pragma mark - 276 277 278 BViewState::BViewState() 279 { 280 fViewMode = kListMode; 281 fLastIconMode = 0; 282 fIconSize = 32; 283 fListOrigin.Set(0, 0); 284 fIconOrigin.Set(0, 0); 285 fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE); 286 fPrimarySortType = B_STRING_TYPE; 287 fSecondarySortAttr = 0; 288 fSecondarySortType = 0; 289 fReverseSort = false; 290 fStateNeedsSaving = false; 291 } 292 293 294 BViewState::BViewState(BMallocIO *stream, bool endianSwap) 295 { 296 stream->Read(&fViewMode, sizeof(uint32)); 297 stream->Read(&fLastIconMode, sizeof(uint32)); 298 stream->Read(&fListOrigin, sizeof(BPoint)); 299 stream->Read(&fIconOrigin, sizeof(BPoint)); 300 stream->Read(&fPrimarySortAttr, sizeof(uint32)); 301 stream->Read(&fPrimarySortType, sizeof(uint32)); 302 stream->Read(&fSecondarySortAttr, sizeof(uint32)); 303 stream->Read(&fSecondarySortType, sizeof(uint32)); 304 stream->Read(&fReverseSort, sizeof(bool)); 305 stream->Read(&fIconSize, sizeof(uint32)); 306 307 if (endianSwap) { 308 PRINT(("endian swapping view state\n")); 309 fViewMode = B_SWAP_INT32(fViewMode); 310 fLastIconMode = B_SWAP_INT32(fLastIconMode); 311 fIconSize = B_SWAP_INT32(fIconSize); 312 swap_data(B_POINT_TYPE, &fListOrigin, sizeof(fListOrigin), B_SWAP_ALWAYS); 313 swap_data(B_POINT_TYPE, &fIconOrigin, sizeof(fIconOrigin), B_SWAP_ALWAYS); 314 fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr); 315 fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr); 316 fPrimarySortType = B_SWAP_INT32(fPrimarySortType); 317 fSecondarySortType = B_SWAP_INT32(fSecondarySortType); 318 } 319 320 fStateNeedsSaving = false; 321 322 _Sanitize(this, true); 323 } 324 325 326 BViewState::BViewState(const BMessage &message) 327 { 328 message.FindInt32(kViewStateViewModeName, (int32 *)&fViewMode); 329 message.FindInt32(kViewStateLastIconModeName, (int32 *)&fLastIconMode); 330 message.FindPoint(kViewStateListOriginName, &fListOrigin); 331 message.FindPoint(kViewStateIconOriginName, &fIconOrigin); 332 message.FindInt32(kViewStatePrimarySortAttrName, (int32 *)&fPrimarySortAttr); 333 message.FindInt32(kViewStatePrimarySortTypeName, (int32 *)&fPrimarySortType); 334 message.FindInt32(kViewStateSecondarySortAttrName, (int32 *)&fSecondarySortAttr); 335 message.FindInt32(kViewStateSecondarySortTypeName, (int32 *)&fSecondarySortType); 336 message.FindBool(kViewStateReverseSortName, &fReverseSort); 337 fStateNeedsSaving = false; 338 339 _Sanitize(this, true); 340 } 341 342 343 void 344 BViewState::ArchiveToStream(BMallocIO *stream) const 345 { 346 // write class identifier and verison info 347 uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE); 348 stream->Write(&key, sizeof(key)); 349 int32 version = kViewStateArchiveVersion; 350 stream->Write(&version, sizeof(version)); 351 352 stream->Write(&fViewMode, sizeof(uint32)); 353 stream->Write(&fLastIconMode, sizeof(uint32)); 354 stream->Write(&fListOrigin, sizeof(BPoint)); 355 stream->Write(&fIconOrigin, sizeof(BPoint)); 356 stream->Write(&fPrimarySortAttr, sizeof(uint32)); 357 stream->Write(&fPrimarySortType, sizeof(uint32)); 358 stream->Write(&fSecondarySortAttr, sizeof(uint32)); 359 stream->Write(&fSecondarySortType, sizeof(uint32)); 360 stream->Write(&fReverseSort, sizeof(bool)); 361 stream->Write(&fIconSize, sizeof(uint32)); 362 } 363 364 365 void 366 BViewState::ArchiveToMessage(BMessage &message) const 367 { 368 message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion); 369 370 message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode)); 371 message.AddInt32(kViewStateLastIconModeName, static_cast<int32>(fLastIconMode)); 372 message.AddPoint(kViewStateListOriginName, fListOrigin); 373 message.AddPoint(kViewStateIconOriginName, fIconOrigin); 374 message.AddInt32(kViewStatePrimarySortAttrName, static_cast<int32>(fPrimarySortAttr)); 375 message.AddInt32(kViewStatePrimarySortTypeName, static_cast<int32>(fPrimarySortType)); 376 message.AddInt32(kViewStateSecondarySortAttrName, static_cast<int32>(fSecondarySortAttr)); 377 message.AddInt32(kViewStateSecondarySortTypeName, static_cast<int32>(fSecondarySortType)); 378 message.AddBool(kViewStateReverseSortName, fReverseSort); 379 message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize)); 380 } 381 382 383 BViewState * 384 BViewState::InstantiateFromStream(BMallocIO *stream, bool endianSwap) 385 { 386 // compare stream header in canonical form 387 uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE); 388 int32 version = kViewStateArchiveVersion; 389 390 if (endianSwap) { 391 key = SwapUInt32(key); 392 version = SwapInt32(version); 393 } 394 395 if (!ValidateStream(stream, key, version)) 396 return NULL; 397 398 return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap)); 399 } 400 401 402 BViewState * 403 BViewState::InstantiateFromMessage(const BMessage &message) 404 { 405 int32 version = kViewStateArchiveVersion; 406 407 int32 messageVersion; 408 if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK) 409 return NULL; 410 411 if (version != messageVersion) 412 return NULL; 413 414 return _Sanitize(new (std::nothrow) BViewState(message)); 415 } 416 417 418 BViewState * 419 BViewState::_Sanitize(BViewState *state, bool fixOnly) 420 { 421 if (state == NULL) 422 return NULL; 423 424 if (state->fViewMode == kListMode) { 425 if (state->fListOrigin.x < 0) 426 state->fListOrigin.x = 0; 427 if (state->fListOrigin.y < 0) 428 state->fListOrigin.y = 0; 429 } 430 if (state->fIconSize < 16) 431 state->fIconSize = 16; 432 if (state->fIconSize > 64) 433 state->fIconSize = 64; 434 435 if (fixOnly) 436 return state; 437 438 // do a sanity check here 439 if ((state->fViewMode != kListMode 440 && state->fViewMode != kIconMode 441 && state->fViewMode != kMiniIconMode 442 && state->fViewMode != kScaleIconMode 443 && state->fViewMode != 0) 444 || (state->fLastIconMode != kListMode 445 && state->fLastIconMode != kIconMode 446 && state->fLastIconMode != kMiniIconMode 447 && state->fLastIconMode != kScaleIconMode 448 && state->fLastIconMode != 0)) { 449 PRINT(("Bad data instantiating ViewState, view mode %x, lastIconMode %x\n", 450 state->fViewMode, state->fLastIconMode)); 451 452 delete state; 453 return NULL; 454 } 455 #if DEBUG 456 // TODO: Whatever this is supposed to mean, fix it. 457 // else if (endianSwap) 458 // PRINT(("Instantiated foreign view state ok\n")); 459 #endif 460 461 return state; 462 } 463 464