xref: /haiku/src/kits/tracker/ViewState.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
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 *kColumnStatFieldName = "BColumn:fStatField";
59 const char *kColumnEditableName = "BColumn:fEditable";
60 
61 const char *kViewStateVersionName = "ViewState:version";
62 const char *kViewStateViewModeName = "ViewState:fViewMode";
63 const char *kViewStateLastIconModeName = "ViewState:fLastIconMode";
64 const char *kViewStateListOriginName = "ViewState:fListOrigin";
65 const char *kViewStateIconOriginName = "ViewState:fIconOrigin";
66 const char *kViewStatePrimarySortAttrName = "ViewState:fPrimarySortAttr";
67 const char *kViewStatePrimarySortTypeName = "ViewState:fPrimarySortType";
68 const char *kViewStateSecondarySortAttrName = "ViewState:fSecondarySortAttr";
69 const char *kViewStateSecondarySortTypeName = "ViewState:fSecondarySortType";
70 const char *kViewStateReverseSortName = "ViewState:fReverseSort";
71 const char *kViewStateIconSizeName = "ViewState:fIconSize";
72 
73 
74 BColumn::BColumn(const char *title, float offset, float width, alignment align,
75 		const char *attributeName, uint32 attrType, bool statField,
76 		bool editable)
77 	:
78 	fTitle(title),
79 	fAttrName(attributeName)
80 {
81 	fOffset = offset;
82 	fWidth = width;
83 	fAlignment = align;
84 	fAttrHash = AttrHashString(attributeName, attrType);
85 	fAttrType = attrType;
86 	fStatField = statField;
87 	fEditable = editable;
88 }
89 
90 
91 BColumn::~BColumn()
92 {
93 }
94 
95 
96 BColumn::BColumn(BMallocIO *stream, bool endianSwap)
97 {
98 	StringFromStream(&fTitle, stream, endianSwap);
99 	stream->Read(&fOffset, sizeof(float));
100 	stream->Read(&fWidth, sizeof(float));
101 	stream->Read(&fAlignment, sizeof(alignment));
102 	StringFromStream(&fAttrName, stream, endianSwap);
103 	stream->Read(&fAttrHash, sizeof(uint32));
104 	stream->Read(&fAttrType, sizeof(uint32));
105 	stream->Read(&fStatField, sizeof(bool));
106 	stream->Read(&fEditable, sizeof(bool));
107 
108 	if (endianSwap) {
109 		PRINT(("endian swapping column\n"));
110 		fOffset = B_SWAP_FLOAT(fOffset);
111 		fWidth = B_SWAP_FLOAT(fWidth);
112 		STATIC_ASSERT(sizeof(BColumn::fAlignment) == sizeof(int32));
113 		fAlignment = (alignment)B_SWAP_INT32(fAlignment);
114 		fAttrHash = B_SWAP_INT32(fAttrHash);
115 		fAttrType = B_SWAP_INT32(fAttrType);
116 	}
117 }
118 
119 
120 BColumn::BColumn(const BMessage &message, int32 index)
121 {
122 	message.FindString(kColumnTitleName, index, &fTitle);
123 	message.FindFloat(kColumnOffsetName, index, &fOffset);
124 	message.FindFloat(kColumnWidthName, index, &fWidth);
125 	message.FindInt32(kColumnAlignmentName, index, (int32 *)&fAlignment);
126 	message.FindString(kColumnAttrName, index, &fAttrName);
127 	message.FindInt32(kColumnAttrHashName, index, (int32 *)&fAttrHash);
128 	message.FindInt32(kColumnAttrTypeName, index, (int32 *)&fAttrType);
129 	message.FindBool(kColumnStatFieldName, index, &fStatField);
130 	message.FindBool(kColumnEditableName, index, &fEditable);
131 }
132 
133 
134 BColumn *
135 BColumn::InstantiateFromStream(BMallocIO *stream, bool endianSwap)
136 {
137 	// compare stream header in canonical form
138 	uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE);
139 	int32 version = kColumnStateArchiveVersion;
140 
141 	if (endianSwap) {
142 		key = SwapUInt32(key);
143 		version = SwapInt32(version);
144 	}
145 
146 //	PRINT(("validating key %x, version %d\n", key, version));
147 	if (!ValidateStream(stream, key, version))
148 		return 0;
149 
150 //	PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : ""));
151 	return _Sanitize(new (std::nothrow) BColumn(stream, endianSwap));
152 }
153 
154 
155 BColumn *
156 BColumn::InstantiateFromMessage(const BMessage &message, int32 index)
157 {
158 	int32 version = kColumnStateArchiveVersion;
159 	int32 messageVersion;
160 
161 	if (message.FindInt32(kColumnVersionName, index, &messageVersion) != B_OK)
162 		return NULL;
163 
164 	if (version != messageVersion)
165 		return NULL;
166 
167 	return _Sanitize(new (std::nothrow) BColumn(message, index));
168 }
169 
170 
171 void
172 BColumn::ArchiveToStream(BMallocIO *stream) const
173 {
174 	// write class identifier and version info
175 	uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE);
176 	stream->Write(&key, sizeof(uint32));
177 	int32 version = kColumnStateArchiveVersion;
178 	stream->Write(&version, sizeof(int32));
179 
180 //	PRINT(("ArchiveToStream column, key %x, version %d\n", key, version));
181 
182 	StringToStream(&fTitle, stream);
183 	stream->Write(&fOffset, sizeof(float));
184 	stream->Write(&fWidth, sizeof(float));
185 	stream->Write(&fAlignment, sizeof(alignment));
186 	StringToStream(&fAttrName, stream);
187 	stream->Write(&fAttrHash, sizeof(uint32));
188 	stream->Write(&fAttrType, sizeof(uint32));
189 	stream->Write(&fStatField, sizeof(bool));
190 	stream->Write(&fEditable, sizeof(bool));
191 }
192 
193 
194 void
195 BColumn::ArchiveToMessage(BMessage &message) const
196 {
197 	message.AddInt32(kColumnVersionName, kColumnStateArchiveVersion);
198 
199 	message.AddString(kColumnTitleName, fTitle);
200 	message.AddFloat(kColumnOffsetName, fOffset);
201 	message.AddFloat(kColumnWidthName, fWidth);
202 	message.AddInt32(kColumnAlignmentName, fAlignment);
203 	message.AddString(kColumnAttrName, fAttrName);
204 	message.AddInt32(kColumnAttrHashName, static_cast<int32>(fAttrHash));
205 	message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType));
206 	message.AddBool(kColumnStatFieldName, fStatField);
207 	message.AddBool(kColumnEditableName, fEditable);
208 }
209 
210 
211 BColumn *
212 BColumn::_Sanitize(BColumn *column)
213 {
214 	if (column == NULL)
215 		return NULL;
216 
217 	// sanity-check the resulting column
218 	if (column->fTitle.Length() > 500
219 		|| column->fOffset < 0
220 		|| column->fOffset > 10000
221 		|| column->fWidth < 0
222 		|| column->fWidth > 10000
223 		|| (int32)column->fAlignment < B_ALIGN_LEFT
224 		|| (int32)column->fAlignment > B_ALIGN_CENTER
225 		|| column->fAttrName.Length() > 500) {
226 		PRINT(("column data not valid\n"));
227 		delete column;
228 		return NULL;
229 	}
230 #if DEBUG
231 	else if (endianSwap)
232 		PRINT(("Instantiated foreign column ok\n"));
233 #endif
234 
235 	return column;
236 }
237 
238 
239 //	#pragma mark -
240 
241 
242 BViewState::BViewState()
243 {
244 	fViewMode = kListMode;
245 	fLastIconMode = 0;
246 	fIconSize = 32;
247 	fListOrigin.Set(0, 0);
248 	fIconOrigin.Set(0, 0);
249 	fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE);
250 	fPrimarySortType = B_STRING_TYPE;
251 	fSecondarySortAttr = 0;
252 	fSecondarySortType = 0;
253 	fReverseSort = false;
254 	fStateNeedsSaving = false;
255 }
256 
257 
258 BViewState::BViewState(BMallocIO *stream, bool endianSwap)
259 {
260 	stream->Read(&fViewMode, sizeof(uint32));
261 	stream->Read(&fLastIconMode, sizeof(uint32));
262 	stream->Read(&fListOrigin, sizeof(BPoint));
263 	stream->Read(&fIconOrigin, sizeof(BPoint));
264 	stream->Read(&fPrimarySortAttr, sizeof(uint32));
265 	stream->Read(&fPrimarySortType, sizeof(uint32));
266 	stream->Read(&fSecondarySortAttr, sizeof(uint32));
267 	stream->Read(&fSecondarySortType, sizeof(uint32));
268 	stream->Read(&fReverseSort, sizeof(bool));
269 	stream->Read(&fIconSize, sizeof(uint32));
270 
271 	if (endianSwap) {
272 		PRINT(("endian swapping view state\n"));
273 		fViewMode = B_SWAP_INT32(fViewMode);
274 		fLastIconMode = B_SWAP_INT32(fLastIconMode);
275 		fIconSize = B_SWAP_INT32(fIconSize);
276 		swap_data(B_POINT_TYPE, &fListOrigin, sizeof(fListOrigin), B_SWAP_ALWAYS);
277 		swap_data(B_POINT_TYPE, &fIconOrigin, sizeof(fIconOrigin), B_SWAP_ALWAYS);
278 		fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr);
279 		fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr);
280 		fPrimarySortType = B_SWAP_INT32(fPrimarySortType);
281 		fSecondarySortType = B_SWAP_INT32(fSecondarySortType);
282 	}
283 
284 	fStateNeedsSaving = false;
285 
286 	_Sanitize(this, true);
287 }
288 
289 
290 BViewState::BViewState(const BMessage &message)
291 {
292 	message.FindInt32(kViewStateViewModeName, (int32 *)&fViewMode);
293 	message.FindInt32(kViewStateLastIconModeName, (int32 *)&fLastIconMode);
294 	message.FindPoint(kViewStateListOriginName, &fListOrigin);
295 	message.FindPoint(kViewStateIconOriginName, &fIconOrigin);
296 	message.FindInt32(kViewStatePrimarySortAttrName, (int32 *)&fPrimarySortAttr);
297 	message.FindInt32(kViewStatePrimarySortTypeName, (int32 *)&fPrimarySortType);
298 	message.FindInt32(kViewStateSecondarySortAttrName, (int32 *)&fSecondarySortAttr);
299 	message.FindInt32(kViewStateSecondarySortTypeName, (int32 *)&fSecondarySortType);
300 	message.FindBool(kViewStateReverseSortName, &fReverseSort);
301 	fStateNeedsSaving = false;
302 
303 	_Sanitize(this, true);
304 }
305 
306 
307 void
308 BViewState::ArchiveToStream(BMallocIO *stream) const
309 {
310 	// write class identifier and verison info
311 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
312 	stream->Write(&key, sizeof(key));
313 	int32 version = kViewStateArchiveVersion;
314 	stream->Write(&version, sizeof(version));
315 
316 	stream->Write(&fViewMode, sizeof(uint32));
317 	stream->Write(&fLastIconMode, sizeof(uint32));
318 	stream->Write(&fListOrigin, sizeof(BPoint));
319 	stream->Write(&fIconOrigin, sizeof(BPoint));
320 	stream->Write(&fPrimarySortAttr, sizeof(uint32));
321 	stream->Write(&fPrimarySortType, sizeof(uint32));
322 	stream->Write(&fSecondarySortAttr, sizeof(uint32));
323 	stream->Write(&fSecondarySortType, sizeof(uint32));
324 	stream->Write(&fReverseSort, sizeof(bool));
325 	stream->Write(&fIconSize, sizeof(uint32));
326 }
327 
328 
329 void
330 BViewState::ArchiveToMessage(BMessage &message) const
331 {
332 	message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion);
333 
334 	message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode));
335 	message.AddInt32(kViewStateLastIconModeName, static_cast<int32>(fLastIconMode));
336 	message.AddPoint(kViewStateListOriginName, fListOrigin);
337 	message.AddPoint(kViewStateIconOriginName, fIconOrigin);
338 	message.AddInt32(kViewStatePrimarySortAttrName, static_cast<int32>(fPrimarySortAttr));
339 	message.AddInt32(kViewStatePrimarySortTypeName, static_cast<int32>(fPrimarySortType));
340 	message.AddInt32(kViewStateSecondarySortAttrName, static_cast<int32>(fSecondarySortAttr));
341 	message.AddInt32(kViewStateSecondarySortTypeName, static_cast<int32>(fSecondarySortType));
342 	message.AddBool(kViewStateReverseSortName, fReverseSort);
343 	message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize));
344 }
345 
346 
347 BViewState *
348 BViewState::InstantiateFromStream(BMallocIO *stream, bool endianSwap)
349 {
350 	// compare stream header in canonical form
351 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
352 	int32 version = kViewStateArchiveVersion;
353 
354 	if (endianSwap) {
355 		key = SwapUInt32(key);
356 		version = SwapInt32(version);
357 	}
358 
359 	if (!ValidateStream(stream, key, version))
360 		return NULL;
361 
362 	return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap));
363 }
364 
365 
366 BViewState *
367 BViewState::InstantiateFromMessage(const BMessage &message)
368 {
369 	int32 version = kViewStateArchiveVersion;
370 
371 	int32 messageVersion;
372 	if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK)
373 		return NULL;
374 
375 	if (version != messageVersion)
376 		return NULL;
377 
378 	return _Sanitize(new (std::nothrow) BViewState(message));
379 }
380 
381 
382 BViewState *
383 BViewState::_Sanitize(BViewState *state, bool fixOnly)
384 {
385 	if (state == NULL)
386 		return NULL;
387 
388 	if (state->fViewMode == kListMode) {
389 		if (state->fListOrigin.x < 0)
390 			state->fListOrigin.x = 0;
391 		if (state->fListOrigin.y < 0)
392 			state->fListOrigin.y = 0;
393 	}
394 	if (state->fIconSize < 16)
395 		state->fIconSize = 16;
396 	if (state->fIconSize > 64)
397 		state->fIconSize = 64;
398 
399 	if (fixOnly)
400 		return state;
401 
402 	// do a sanity check here
403 	if ((state->fViewMode != kListMode
404 			&& state->fViewMode != kIconMode
405 			&& state->fViewMode != kMiniIconMode
406 			&& state->fViewMode != kScaleIconMode
407 			&& state->fViewMode != 0)
408 		|| (state->fLastIconMode != kListMode
409 			&& state->fLastIconMode != kIconMode
410 			&& state->fLastIconMode != kMiniIconMode
411 			&& state->fLastIconMode != kScaleIconMode
412 			&& state->fLastIconMode != 0)) {
413 		PRINT(("Bad data instantiating ViewState, view mode %x, lastIconMode %x\n",
414 			state->fViewMode, state->fLastIconMode));
415 
416 		delete state;
417 		return NULL;
418 	}
419 #if DEBUG
420 	else if (endianSwap)
421 		PRINT(("Instantiated foreign view state ok\n"));
422 #endif
423 
424 	return state;
425 }
426 
427