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
BColumn(const char * title,float width,alignment align,const char * attributeName,uint32 attrType,const char * displayAs,bool statField,bool editable)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
BColumn(const char * title,float width,alignment align,const char * attributeName,uint32 attrType,bool statField,bool editable)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
~BColumn()102 BColumn::~BColumn()
103 {
104 }
105
106
BColumn(BMallocIO * stream,int32 version,bool endianSwap)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
BColumn(const BMessage & message,int32 index)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
_Init(const char * title,float width,alignment align,const char * attributeName,uint32 attrType,const char * displayAs,bool statField,bool editable)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
_Scale()199 BColumn::_Scale()
200 {
201 return (be_plain_font->Size() / 12.0f);
202 }
203
204
205 BColumn*
InstantiateFromStream(BMallocIO * stream,bool endianSwap)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*
InstantiateFromMessage(const BMessage & message,int32 index)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
ArchiveToStream(BMallocIO * stream) const248 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
ArchiveToMessage(BMessage & message) const275 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*
_Sanitize(BColumn * column)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
BViewState()327 BViewState::BViewState()
328 {
329 _Init();
330 _StorePreviousState();
331 }
332
333
BViewState(BMallocIO * stream,bool endianSwap)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
BViewState(const BMessage & message)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
ArchiveToStream(BMallocIO * stream)395 BViewState::ArchiveToStream(BMallocIO* stream)
396 {
397 _ArchiveToStream(stream);
398 _StorePreviousState();
399 }
400
401
402 void
ArchiveToMessage(BMessage & message)403 BViewState::ArchiveToMessage(BMessage &message)
404 {
405 _ArchiveToMessage(message);
406 _StorePreviousState();
407 }
408
409
410 BViewState*
InstantiateFromStream(BMallocIO * stream,bool endianSwap)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*
InstantiateFromMessage(const BMessage & message)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
_Init()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
_StorePreviousState()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*
_Sanitize(BViewState * state,bool fixOnly)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
_ArchiveToStream(BMallocIO * stream) const534 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
_ArchiveToMessage(BMessage & message) const557 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