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