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 36 #include <Debug.h> 37 #include <AppDefs.h> 38 #include <InterfaceDefs.h> 39 40 #include "Attributes.h" 41 #include "Commands.h" 42 #include "PoseView.h" 43 #include "Utilities.h" 44 #include "ViewState.h" 45 46 #include <new> 47 #include <string.h> 48 #include <stdlib.h> 49 50 51 const char* kColumnVersionName = "BColumn:version"; 52 const char* kColumnTitleName = "BColumn:fTitle"; 53 const char* kColumnOffsetName = "BColumn:fOffset"; 54 const char* kColumnWidthName = "BColumn:fWidth"; 55 const char* kColumnAlignmentName = "BColumn:fAlignment"; 56 const char* kColumnAttrName = "BColumn:fAttrName"; 57 const char* kColumnAttrHashName = "BColumn:fAttrHash"; 58 const char* kColumnAttrTypeName = "BColumn:fAttrType"; 59 const char* kColumnDisplayAsName = "BColumn:fDisplayAs"; 60 const char* kColumnStatFieldName = "BColumn:fStatField"; 61 const char* kColumnEditableName = "BColumn:fEditable"; 62 63 const char* kViewStateVersionName = "ViewState:version"; 64 const char* kViewStateViewModeName = "ViewState:fViewMode"; 65 const char* kViewStateLastIconModeName = "ViewState:fLastIconMode"; 66 const char* kViewStateListOriginName = "ViewState:fListOrigin"; 67 const char* kViewStateIconOriginName = "ViewState:fIconOrigin"; 68 const char* kViewStatePrimarySortAttrName = "ViewState:fPrimarySortAttr"; 69 const char* kViewStatePrimarySortTypeName = "ViewState:fPrimarySortType"; 70 const char* kViewStateSecondarySortAttrName = "ViewState:fSecondarySortAttr"; 71 const char* kViewStateSecondarySortTypeName = "ViewState:fSecondarySortType"; 72 const char* kViewStateReverseSortName = "ViewState:fReverseSort"; 73 const char* kViewStateIconSizeName = "ViewState:fIconSize"; 74 const char* kViewStateLastIconSizeName = "ViewState:fLastIconSize"; 75 76 77 static const int32 kColumnStateMinArchiveVersion = 21; 78 // bump version when layout changes 79 80 81 // #pragma mark - BColumn 82 83 84 BColumn::BColumn(const char* title, float offset, float width, 85 alignment align, const char* attributeName, uint32 attrType, 86 const char* displayAs, bool statField, bool editable) 87 { 88 _Init(title, offset, width, align, attributeName, attrType, displayAs, 89 statField, editable); 90 } 91 92 93 BColumn::BColumn(const char* title, float offset, float width, 94 alignment align, const char* attributeName, uint32 attrType, 95 bool statField, bool editable) 96 { 97 _Init(title, offset, width, align, attributeName, attrType, NULL, 98 statField, editable); 99 } 100 101 102 BColumn::~BColumn() 103 { 104 } 105 106 107 BColumn::BColumn(BMallocIO* stream, int32 version, bool endianSwap) 108 { 109 StringFromStream(&fTitle, stream, endianSwap); 110 stream->Read(&fOffset, sizeof(float)); 111 stream->Read(&fWidth, sizeof(float)); 112 stream->Read(&fAlignment, sizeof(alignment)); 113 StringFromStream(&fAttrName, stream, endianSwap); 114 stream->Read(&fAttrHash, sizeof(uint32)); 115 stream->Read(&fAttrType, sizeof(uint32)); 116 stream->Read(&fStatField, sizeof(bool)); 117 stream->Read(&fEditable, sizeof(bool)); 118 if (version == kColumnStateArchiveVersion) 119 StringFromStream(&fDisplayAs, stream, endianSwap); 120 121 if (endianSwap) { 122 PRINT(("endian swapping column\n")); 123 fOffset = B_SWAP_FLOAT(fOffset); 124 fWidth = B_SWAP_FLOAT(fWidth); 125 STATIC_ASSERT(sizeof(alignment) == sizeof(int32)); 126 fAlignment = (alignment)B_SWAP_INT32(fAlignment); 127 fAttrHash = B_SWAP_INT32(fAttrHash); 128 fAttrType = B_SWAP_INT32(fAttrType); 129 } 130 } 131 132 133 BColumn::BColumn(const BMessage &message, int32 index) 134 { 135 if (message.FindString(kColumnTitleName, index, &fTitle) != B_OK) 136 fTitle.SetTo(B_EMPTY_STRING); 137 138 if (message.FindFloat(kColumnOffsetName, index, &fOffset) != B_OK) 139 fOffset = -1.0f; 140 141 if (message.FindFloat(kColumnWidthName, index, &fWidth) != B_OK) 142 fWidth = -1.0f; 143 144 if (message.FindInt32(kColumnAlignmentName, index, (int32*)&fAlignment) 145 != B_OK) { 146 fAlignment = B_ALIGN_LEFT; 147 } 148 149 if (message.FindString(kColumnAttrName, index, &fAttrName) != B_OK) 150 fAttrName = BString(B_EMPTY_STRING); 151 152 if (message.FindInt32(kColumnAttrHashName, index, (int32*)&fAttrHash) 153 != B_OK) { 154 fAttrHash = 0; 155 } 156 157 if (message.FindInt32(kColumnAttrTypeName, index, (int32*)&fAttrType) 158 != B_OK) { 159 fAttrType = 0; 160 } 161 162 if (message.FindString(kColumnDisplayAsName, index, &fDisplayAs) != B_OK) 163 fDisplayAs.SetTo(B_EMPTY_STRING); 164 165 if (message.FindBool(kColumnStatFieldName, index, &fStatField) != B_OK) 166 fStatField = false; 167 168 if (message.FindBool(kColumnEditableName, index, &fEditable) != B_OK) 169 fEditable = false; 170 171 } 172 173 174 void 175 BColumn::_Init(const char* title, float offset, float width, 176 alignment align, const char* attributeName, uint32 attrType, 177 const char* displayAs, bool statField, bool editable) 178 { 179 fTitle = title; 180 fAttrName = attributeName; 181 fDisplayAs = displayAs; 182 fOffset = offset; 183 fWidth = width; 184 fAlignment = align; 185 fAttrHash = AttrHashString(attributeName, attrType); 186 fAttrType = attrType; 187 fStatField = statField; 188 fEditable = editable; 189 } 190 191 192 BColumn* 193 BColumn::InstantiateFromStream(BMallocIO* stream, bool endianSwap) 194 { 195 // compare stream header in canonical form 196 197 // we can't use ValidateStream(), as we preserve backwards compatibility 198 int32 version; 199 uint32 key; 200 if (stream->Read(&key, sizeof(uint32)) <= 0 201 || stream->Read(&version, sizeof(int32)) <=0) 202 return 0; 203 204 if (endianSwap) { 205 key = SwapUInt32(key); 206 version = SwapInt32(version); 207 } 208 209 if (key != AttrHashString("BColumn", B_OBJECT_TYPE) 210 || version < kColumnStateMinArchiveVersion) 211 return 0; 212 213 // PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : "")); 214 return _Sanitize(new (std::nothrow) BColumn(stream, version, endianSwap)); 215 } 216 217 218 BColumn* 219 BColumn::InstantiateFromMessage(const BMessage &message, int32 index) 220 { 221 int32 version = kColumnStateArchiveVersion; 222 int32 messageVersion; 223 224 if (message.FindInt32(kColumnVersionName, index, &messageVersion) != B_OK) 225 return NULL; 226 227 if (version != messageVersion) 228 return NULL; 229 230 return _Sanitize(new (std::nothrow) BColumn(message, index)); 231 } 232 233 234 void 235 BColumn::ArchiveToStream(BMallocIO* stream) const 236 { 237 // write class identifier and version info 238 uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE); 239 stream->Write(&key, sizeof(uint32)); 240 int32 version = kColumnStateArchiveVersion; 241 stream->Write(&version, sizeof(int32)); 242 243 // PRINT(("ArchiveToStream column, key %x, version %d\n", key, version)); 244 245 StringToStream(&fTitle, stream); 246 stream->Write(&fOffset, sizeof(float)); 247 stream->Write(&fWidth, sizeof(float)); 248 stream->Write(&fAlignment, sizeof(alignment)); 249 StringToStream(&fAttrName, stream); 250 stream->Write(&fAttrHash, sizeof(uint32)); 251 stream->Write(&fAttrType, sizeof(uint32)); 252 stream->Write(&fStatField, sizeof(bool)); 253 stream->Write(&fEditable, sizeof(bool)); 254 StringToStream(&fDisplayAs, stream); 255 } 256 257 258 void 259 BColumn::ArchiveToMessage(BMessage &message) const 260 { 261 message.AddInt32(kColumnVersionName, kColumnStateArchiveVersion); 262 263 message.AddString(kColumnTitleName, fTitle); 264 message.AddFloat(kColumnOffsetName, fOffset); 265 message.AddFloat(kColumnWidthName, fWidth); 266 message.AddInt32(kColumnAlignmentName, fAlignment); 267 message.AddString(kColumnAttrName, fAttrName); 268 message.AddInt32(kColumnAttrHashName, static_cast<int32>(fAttrHash)); 269 message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType)); 270 message.AddString(kColumnDisplayAsName, fDisplayAs.String()); 271 message.AddBool(kColumnStatFieldName, fStatField); 272 message.AddBool(kColumnEditableName, fEditable); 273 } 274 275 276 BColumn* 277 BColumn::_Sanitize(BColumn* column) 278 { 279 if (column == NULL) 280 return NULL; 281 282 // sanity-check the resulting column 283 if (column->fTitle.Length() > 500 284 || column->fOffset < 0 285 || column->fOffset > 10000 286 || column->fWidth < 0 287 || column->fWidth > 10000 288 || (int32)column->fAlignment < B_ALIGN_LEFT 289 || (int32)column->fAlignment > B_ALIGN_CENTER 290 || column->fAttrName.Length() > 500) { 291 PRINT(("column data not valid\n")); 292 delete column; 293 return NULL; 294 } 295 #if DEBUG 296 // TODO: Whatever this is supposed to mean, fix it. 297 // else if (endianSwap) 298 // PRINT(("Instantiated foreign column ok\n")); 299 #endif 300 301 return column; 302 } 303 304 305 // #pragma mark - BViewState 306 307 308 BViewState::BViewState() 309 { 310 _Init(); 311 _StorePreviousState(); 312 } 313 314 315 BViewState::BViewState(BMallocIO* stream, bool endianSwap) 316 { 317 _Init(); 318 stream->Read(&fViewMode, sizeof(uint32)); 319 stream->Read(&fLastIconMode, sizeof(uint32)); 320 stream->Read(&fListOrigin, sizeof(BPoint)); 321 stream->Read(&fIconOrigin, sizeof(BPoint)); 322 stream->Read(&fPrimarySortAttr, sizeof(uint32)); 323 stream->Read(&fPrimarySortType, sizeof(uint32)); 324 stream->Read(&fSecondarySortAttr, sizeof(uint32)); 325 stream->Read(&fSecondarySortType, sizeof(uint32)); 326 stream->Read(&fReverseSort, sizeof(bool)); 327 stream->Read(&fIconSize, sizeof(uint32)); 328 stream->Read(&fLastIconSize, sizeof(uint32)); 329 330 if (endianSwap) { 331 PRINT(("endian swapping view state\n")); 332 fViewMode = B_SWAP_INT32(fViewMode); 333 fLastIconMode = B_SWAP_INT32(fLastIconMode); 334 fIconSize = B_SWAP_INT32(fIconSize); 335 fLastIconSize = B_SWAP_INT32(fLastIconSize); 336 swap_data(B_POINT_TYPE, &fListOrigin, 337 sizeof(fListOrigin), B_SWAP_ALWAYS); 338 swap_data(B_POINT_TYPE, &fIconOrigin, 339 sizeof(fIconOrigin), B_SWAP_ALWAYS); 340 fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr); 341 fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr); 342 fPrimarySortType = B_SWAP_INT32(fPrimarySortType); 343 fSecondarySortType = B_SWAP_INT32(fSecondarySortType); 344 } 345 346 _StorePreviousState(); 347 _Sanitize(this, true); 348 } 349 350 351 BViewState::BViewState(const BMessage &message) 352 { 353 _Init(); 354 message.FindInt32(kViewStateViewModeName, (int32*)&fViewMode); 355 message.FindInt32(kViewStateLastIconModeName, (int32*)&fLastIconMode); 356 message.FindInt32(kViewStateLastIconSizeName,(int32*)&fLastIconSize); 357 message.FindInt32(kViewStateIconSizeName, (int32*)&fIconSize); 358 message.FindPoint(kViewStateListOriginName, &fListOrigin); 359 message.FindPoint(kViewStateIconOriginName, &fIconOrigin); 360 message.FindInt32(kViewStatePrimarySortAttrName, 361 (int32*)&fPrimarySortAttr); 362 message.FindInt32(kViewStatePrimarySortTypeName, 363 (int32*)&fPrimarySortType); 364 message.FindInt32(kViewStateSecondarySortAttrName, 365 (int32*)&fSecondarySortAttr); 366 message.FindInt32(kViewStateSecondarySortTypeName, 367 (int32*)&fSecondarySortType); 368 message.FindBool(kViewStateReverseSortName, &fReverseSort); 369 370 _StorePreviousState(); 371 _Sanitize(this, true); 372 } 373 374 375 void 376 BViewState::ArchiveToStream(BMallocIO* stream) const 377 { 378 // write class identifier and verison info 379 uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE); 380 stream->Write(&key, sizeof(key)); 381 int32 version = kViewStateArchiveVersion; 382 stream->Write(&version, sizeof(version)); 383 384 stream->Write(&fViewMode, sizeof(uint32)); 385 stream->Write(&fLastIconMode, sizeof(uint32)); 386 stream->Write(&fListOrigin, sizeof(BPoint)); 387 stream->Write(&fIconOrigin, sizeof(BPoint)); 388 stream->Write(&fPrimarySortAttr, sizeof(uint32)); 389 stream->Write(&fPrimarySortType, sizeof(uint32)); 390 stream->Write(&fSecondarySortAttr, sizeof(uint32)); 391 stream->Write(&fSecondarySortType, sizeof(uint32)); 392 stream->Write(&fReverseSort, sizeof(bool)); 393 stream->Write(&fIconSize, sizeof(uint32)); 394 stream->Write(&fLastIconSize, sizeof(uint32)); 395 } 396 397 398 void 399 BViewState::ArchiveToMessage(BMessage &message) const 400 { 401 message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion); 402 403 message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode)); 404 message.AddInt32(kViewStateLastIconModeName, 405 static_cast<int32>(fLastIconMode)); 406 message.AddPoint(kViewStateListOriginName, fListOrigin); 407 message.AddPoint(kViewStateIconOriginName, fIconOrigin); 408 message.AddInt32(kViewStatePrimarySortAttrName, 409 static_cast<int32>(fPrimarySortAttr)); 410 message.AddInt32(kViewStatePrimarySortTypeName, 411 static_cast<int32>(fPrimarySortType)); 412 message.AddInt32(kViewStateSecondarySortAttrName, 413 static_cast<int32>(fSecondarySortAttr)); 414 message.AddInt32(kViewStateSecondarySortTypeName, 415 static_cast<int32>(fSecondarySortType)); 416 message.AddBool(kViewStateReverseSortName, fReverseSort); 417 message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize)); 418 message.AddInt32(kViewStateLastIconSizeName, 419 static_cast<int32>(fLastIconSize)); 420 } 421 422 423 BViewState* 424 BViewState::InstantiateFromStream(BMallocIO* stream, bool endianSwap) 425 { 426 // compare stream header in canonical form 427 uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE); 428 int32 version = kViewStateArchiveVersion; 429 430 if (endianSwap) { 431 key = SwapUInt32(key); 432 version = SwapInt32(version); 433 } 434 435 if (!ValidateStream(stream, key, version)) 436 return NULL; 437 438 return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap)); 439 } 440 441 442 BViewState* 443 BViewState::InstantiateFromMessage(const BMessage &message) 444 { 445 int32 version = kViewStateArchiveVersion; 446 447 int32 messageVersion; 448 if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK) 449 return NULL; 450 451 if (version != messageVersion) 452 return NULL; 453 454 return _Sanitize(new (std::nothrow) BViewState(message)); 455 } 456 457 458 void 459 BViewState::_Init() 460 { 461 fViewMode = kListMode; 462 fLastIconMode = 0; 463 fIconSize = B_LARGE_ICON; 464 fLastIconSize = B_LARGE_ICON; 465 fListOrigin.Set(0, 0); 466 fIconOrigin.Set(0, 0); 467 fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE); 468 fPrimarySortType = B_STRING_TYPE; 469 fSecondarySortAttr = 0; 470 fSecondarySortType = 0; 471 fReverseSort = false; 472 } 473 474 475 void 476 BViewState::_StorePreviousState() 477 { 478 fPreviousViewMode = fViewMode; 479 fPreviousLastIconMode = fLastIconMode; 480 fPreviousIconSize = fIconSize; 481 fPreviousLastIconSize = fLastIconSize; 482 fPreviousListOrigin = fListOrigin; 483 fPreviousIconOrigin = fIconOrigin; 484 fPreviousPrimarySortAttr = fPrimarySortAttr; 485 fPreviousSecondarySortAttr = fSecondarySortAttr; 486 fPreviousPrimarySortType = fPrimarySortType; 487 fPreviousSecondarySortType = fSecondarySortType; 488 fPreviousReverseSort = fReverseSort; 489 } 490 491 492 BViewState* 493 BViewState::_Sanitize(BViewState* state, bool fixOnly) 494 { 495 if (state == NULL) 496 return NULL; 497 498 if (state->fViewMode == kListMode) { 499 if (state->fListOrigin.x < 0) 500 state->fListOrigin.x = 0; 501 502 if (state->fListOrigin.y < 0) 503 state->fListOrigin.y = 0; 504 } 505 if (state->fIconSize < 16) 506 state->fIconSize = 16; 507 508 if (state->fIconSize > 128) 509 state->fIconSize = 128; 510 511 if (state->fLastIconSize < 16) 512 state->fLastIconSize = 16; 513 514 if (state->fLastIconSize > 128) 515 state->fLastIconSize = 128; 516 517 if (fixOnly) 518 return state; 519 520 // do a sanity check here 521 if ((state->fViewMode != kListMode 522 && state->fViewMode != kIconMode 523 && state->fViewMode != kMiniIconMode 524 && state->fViewMode != 0) 525 || (state->fLastIconMode != kListMode 526 && state->fLastIconMode != kIconMode 527 && state->fLastIconMode != kMiniIconMode 528 && state->fLastIconMode != 0)) { 529 PRINT(("Bad data instantiating ViewState, view mode %" B_PRIx32 530 ", lastIconMode %" B_PRIx32 "\n", state->fViewMode, 531 state->fLastIconMode)); 532 533 delete state; 534 return NULL; 535 } 536 #if DEBUG 537 // TODO: Whatever this is supposed to mean, fix it. 538 // else if (endianSwap) 539 // PRINT(("Instantiated foreign view state ok\n")); 540 #endif 541 542 return state; 543 } 544