xref: /haiku/src/kits/interface/View.cpp (revision 7457ccb4b2f4786525d3b7bda42598487d57ab7d)
1 /*
2  * Copyright 2001-2017 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus, superstippi@gmx.de
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Adrian Oanca, adioanca@cotty.iren.ro
9  *		Ingo Weinhold. ingo_weinhold@gmx.de
10  *		Julian Harnath, julian.harnath@rwth-aachen.de
11  *		Joseph Groover, looncraz@looncraz.net
12  */
13 
14 
15 #include <View.h>
16 
17 #include <algorithm>
18 #include <new>
19 
20 #include <math.h>
21 #include <stdio.h>
22 
23 #include <Application.h>
24 #include <Bitmap.h>
25 #include <Button.h>
26 #include <Cursor.h>
27 #include <File.h>
28 #include <GradientLinear.h>
29 #include <GradientRadial.h>
30 #include <GradientRadialFocus.h>
31 #include <GradientDiamond.h>
32 #include <GradientConic.h>
33 #include <InterfaceDefs.h>
34 #include <Layout.h>
35 #include <LayoutContext.h>
36 #include <LayoutUtils.h>
37 #include <MenuBar.h>
38 #include <Message.h>
39 #include <MessageQueue.h>
40 #include <ObjectList.h>
41 #include <Picture.h>
42 #include <Point.h>
43 #include <Polygon.h>
44 #include <PropertyInfo.h>
45 #include <Region.h>
46 #include <ScrollBar.h>
47 #include <Shape.h>
48 #include <Shelf.h>
49 #include <String.h>
50 #include <Window.h>
51 
52 #include <AppMisc.h>
53 #include <AppServerLink.h>
54 #include <binary_compatibility/Interface.h>
55 #include <binary_compatibility/Support.h>
56 #include <MessagePrivate.h>
57 #include <MessageUtils.h>
58 #include <PortLink.h>
59 #include <ServerProtocol.h>
60 #include <ServerProtocolStructs.h>
61 #include <ShapePrivate.h>
62 #include <ToolTip.h>
63 #include <ToolTipManager.h>
64 #include <TokenSpace.h>
65 #include <ViewPrivate.h>
66 
67 using std::nothrow;
68 
69 //#define DEBUG_BVIEW
70 #ifdef DEBUG_BVIEW
71 #	include <stdio.h>
72 #	define STRACE(x) printf x
73 #	define BVTRACE _PrintToStream()
74 #else
75 #	define STRACE(x) ;
76 #	define BVTRACE ;
77 #endif
78 
79 
80 static property_info sViewPropInfo[] = {
81 	{ "Frame", { B_GET_PROPERTY, B_SET_PROPERTY },
82 		{ B_DIRECT_SPECIFIER, 0 }, "The view's frame rectangle.", 0,
83 		{ B_RECT_TYPE }
84 	},
85 	{ "Hidden", { B_GET_PROPERTY, B_SET_PROPERTY },
86 		{ B_DIRECT_SPECIFIER, 0 }, "Whether or not the view is hidden.",
87 		0, { B_BOOL_TYPE }
88 	},
89 	{ "Shelf", { 0 },
90 		{ B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the "
91 			"shelf.", 0
92 	},
93 	{ "View", { B_COUNT_PROPERTIES, 0 },
94 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the number of child views.", 0,
95 		{ B_INT32_TYPE }
96 	},
97 	{ "View", { 0 },
98 		{ B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, 0 },
99 		"Directs the scripting message to the specified view.", 0
100 	},
101 
102 	{ 0 }
103 };
104 
105 
106 //	#pragma mark -
107 
108 
109 static inline uint32
110 get_uint32_color(rgb_color color)
111 {
112 	return B_BENDIAN_TO_HOST_INT32(*(uint32*)&color);
113 		// rgb_color is always in rgba format, no matter what endian;
114 		// we always return the int32 value in host endian.
115 }
116 
117 
118 static inline rgb_color
119 get_rgb_color(uint32 value)
120 {
121 	value = B_HOST_TO_BENDIAN_INT32(value);
122 	return *(rgb_color*)&value;
123 }
124 
125 
126 //	#pragma mark -
127 
128 
129 namespace BPrivate {
130 
131 ViewState::ViewState()
132 {
133 	pen_location.Set(0, 0);
134 	pen_size = 1.0;
135 
136 	// NOTE: the clipping_region is empty
137 	// on construction but it is not used yet,
138 	// we avoid having to keep track of it via
139 	// this flag
140 	clipping_region_used = false;
141 
142 	high_color = (rgb_color){ 0, 0, 0, 255 };
143 	low_color = (rgb_color){ 255, 255, 255, 255 };
144 	view_color = low_color;
145 	which_view_color = B_NO_COLOR;
146 	which_view_color_tint = B_NO_TINT;
147 
148 	which_high_color = B_NO_COLOR;
149 	which_high_color_tint = B_NO_TINT;
150 
151 	which_low_color = B_NO_COLOR;
152 	which_low_color_tint = B_NO_TINT;
153 
154 	pattern = B_SOLID_HIGH;
155 	drawing_mode = B_OP_COPY;
156 
157 	origin.Set(0, 0);
158 
159 	line_join = B_MITER_JOIN;
160 	line_cap = B_BUTT_CAP;
161 	miter_limit = B_DEFAULT_MITER_LIMIT;
162 	fill_rule = B_NONZERO;
163 
164 	alpha_source_mode = B_PIXEL_ALPHA;
165 	alpha_function_mode = B_ALPHA_OVERLAY;
166 
167 	scale = 1.0;
168 
169 	font = *be_plain_font;
170 	font_flags = font.Flags();
171 	font_aliasing = false;
172 
173 	// We only keep the B_VIEW_CLIP_REGION_BIT flag invalidated,
174 	// because we should get the clipping region from app_server.
175 	// The other flags do not need to be included because the data they
176 	// represent is already in sync with app_server - app_server uses the
177 	// same init (default) values.
178 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
179 
180 	archiving_flags = B_VIEW_FRAME_BIT | B_VIEW_RESIZE_BIT;
181 }
182 
183 
184 void
185 ViewState::UpdateServerFontState(BPrivate::PortLink &link)
186 {
187 	link.StartMessage(AS_VIEW_SET_FONT_STATE);
188 	link.Attach<uint16>(font_flags);
189 		// always present
190 
191 	if (font_flags & B_FONT_FAMILY_AND_STYLE)
192 		link.Attach<uint32>(font.FamilyAndStyle());
193 
194 	if (font_flags & B_FONT_SIZE)
195 		link.Attach<float>(font.Size());
196 
197 	if (font_flags & B_FONT_SHEAR)
198 		link.Attach<float>(font.Shear());
199 
200 	if (font_flags & B_FONT_ROTATION)
201 		link.Attach<float>(font.Rotation());
202 
203 	if (font_flags & B_FONT_FALSE_BOLD_WIDTH)
204 		link.Attach<float>(font.FalseBoldWidth());
205 
206 	if (font_flags & B_FONT_SPACING)
207 		link.Attach<uint8>(font.Spacing());
208 
209 	if (font_flags & B_FONT_ENCODING)
210 		link.Attach<uint8>(font.Encoding());
211 
212 	if (font_flags & B_FONT_FACE)
213 		link.Attach<uint16>(font.Face());
214 
215 	if (font_flags & B_FONT_FLAGS)
216 		link.Attach<uint32>(font.Flags());
217 }
218 
219 
220 void
221 ViewState::UpdateServerState(BPrivate::PortLink &link)
222 {
223 	UpdateServerFontState(link);
224 
225 	link.StartMessage(AS_VIEW_SET_STATE);
226 
227 	ViewSetStateInfo info;
228 	info.penLocation = pen_location;
229 	info.penSize = pen_size;
230 	info.highColor = high_color;
231 	info.lowColor = low_color;
232 	info.whichHighColor = which_high_color;
233 	info.whichLowColor = which_low_color;
234 	info.whichHighColorTint = which_high_color_tint;
235 	info.whichLowColorTint = which_low_color_tint;
236 	info.pattern = pattern;
237 	info.drawingMode = drawing_mode;
238 	info.origin = origin;
239 	info.scale = scale;
240 	info.lineJoin = line_join;
241 	info.lineCap = line_cap;
242 	info.miterLimit = miter_limit;
243 	info.fillRule = fill_rule;
244 	info.alphaSourceMode = alpha_source_mode;
245 	info.alphaFunctionMode = alpha_function_mode;
246 	info.fontAntialiasing = font_aliasing;
247 	link.Attach<ViewSetStateInfo>(info);
248 
249 	// BAffineTransform is transmitted as a double array
250 	double _transform[6];
251 	if (transform.Flatten(_transform, sizeof(_transform)) != B_OK)
252 		return;
253 	link.Attach<double[6]>(_transform);
254 
255 	// we send the 'local' clipping region... if we have one...
256 	// TODO: Could be optimized, but is low prio, since most views won't
257 	// have a custom clipping region.
258 	if (clipping_region_used) {
259 		int32 count = clipping_region.CountRects();
260 		link.Attach<int32>(count);
261 		for (int32 i = 0; i < count; i++)
262 			link.Attach<BRect>(clipping_region.RectAt(i));
263 	} else {
264 		// no clipping region
265 		link.Attach<int32>(-1);
266 	}
267 
268 	// Although we might have a 'local' clipping region, when we call
269 	// BView::GetClippingRegion() we ask for the 'global' one and it
270 	// is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag
271 
272 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
273 }
274 
275 
276 void
277 ViewState::UpdateFrom(BPrivate::PortLink &link)
278 {
279 	link.StartMessage(AS_VIEW_GET_STATE);
280 
281 	int32 code;
282 	if (link.FlushWithReply(code) != B_OK
283 		|| code != B_OK)
284 		return;
285 
286 	ViewGetStateInfo info;
287 	link.Read<ViewGetStateInfo>(&info);
288 
289 	// set view's font state
290 	font_flags = B_FONT_ALL;
291 	font.SetFamilyAndStyle(info.fontID);
292 	font.SetSize(info.fontSize);
293 	font.SetShear(info.fontShear);
294 	font.SetRotation(info.fontRotation);
295 	font.SetFalseBoldWidth(info.fontFalseBoldWidth);
296 	font.SetSpacing(info.fontSpacing);
297 	font.SetEncoding(info.fontEncoding);
298 	font.SetFace(info.fontFace);
299 	font.SetFlags(info.fontFlags);
300 
301 	// set view's state
302 	pen_location = info.viewStateInfo.penLocation;
303 	pen_size = info.viewStateInfo.penSize;
304 	high_color = info.viewStateInfo.highColor;
305 	low_color = info.viewStateInfo.lowColor;
306 	pattern = info.viewStateInfo.pattern;
307 	drawing_mode = info.viewStateInfo.drawingMode;
308 	origin = info.viewStateInfo.origin;
309 	scale = info.viewStateInfo.scale;
310 	line_join = info.viewStateInfo.lineJoin;
311 	line_cap = info.viewStateInfo.lineCap;
312 	miter_limit = info.viewStateInfo.miterLimit;
313 	fill_rule = info.viewStateInfo.fillRule;
314 	alpha_source_mode = info.viewStateInfo.alphaSourceMode;
315 	alpha_function_mode = info.viewStateInfo.alphaFunctionMode;
316 	font_aliasing = info.viewStateInfo.fontAntialiasing;
317 
318 	// BAffineTransform is transmitted as a double array
319 	double _transform[6];
320 	link.Read<double[6]>(&_transform);
321 	if (transform.Unflatten(B_AFFINE_TRANSFORM_TYPE, _transform,
322 		sizeof(_transform)) != B_OK) {
323 		return;
324 	}
325 
326 	// read the user clipping
327 	// (that's NOT the current View visible clipping but the additional
328 	// user specified clipping!)
329 	int32 clippingRectCount;
330 	link.Read<int32>(&clippingRectCount);
331 	if (clippingRectCount >= 0) {
332 		clipping_region.MakeEmpty();
333 		for (int32 i = 0; i < clippingRectCount; i++) {
334 			BRect rect;
335 			link.Read<BRect>(&rect);
336 			clipping_region.Include(rect);
337 		}
338 	} else {
339 		// no user clipping used
340 		clipping_region_used = false;
341 	}
342 
343 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
344 }
345 
346 }	// namespace BPrivate
347 
348 
349 //	#pragma mark -
350 
351 
352 // archiving constants
353 namespace {
354 	const char* const kSizesField = "BView:sizes";
355 		// kSizesField = {min, max, pref}
356 	const char* const kAlignmentField = "BView:alignment";
357 	const char* const kLayoutField = "BView:layout";
358 }
359 
360 
361 struct BView::LayoutData {
362 	LayoutData()
363 		:
364 		fMinSize(),
365 		fMaxSize(),
366 		fPreferredSize(),
367 		fAlignment(),
368 		fLayoutInvalidationDisabled(0),
369 		fLayout(NULL),
370 		fLayoutContext(NULL),
371 		fLayoutItems(5, false),
372 		fLayoutValid(true),		// TODO: Rethink these initial values!
373 		fMinMaxValid(true),		//
374 		fLayoutInProgress(false),
375 		fNeedsRelayout(true)
376 	{
377 	}
378 
379 	status_t
380 	AddDataToArchive(BMessage* archive)
381 	{
382 		status_t err = archive->AddSize(kSizesField, fMinSize);
383 
384 		if (err == B_OK)
385 			err = archive->AddSize(kSizesField, fMaxSize);
386 
387 		if (err == B_OK)
388 			err = archive->AddSize(kSizesField, fPreferredSize);
389 
390 		if (err == B_OK)
391 			err = archive->AddAlignment(kAlignmentField, fAlignment);
392 
393 		return err;
394 	}
395 
396 	void
397 	PopulateFromArchive(BMessage* archive)
398 	{
399 		archive->FindSize(kSizesField, 0, &fMinSize);
400 		archive->FindSize(kSizesField, 1, &fMaxSize);
401 		archive->FindSize(kSizesField, 2, &fPreferredSize);
402 		archive->FindAlignment(kAlignmentField, &fAlignment);
403 	}
404 
405 	BSize			fMinSize;
406 	BSize			fMaxSize;
407 	BSize			fPreferredSize;
408 	BAlignment		fAlignment;
409 	int				fLayoutInvalidationDisabled;
410 	BLayout*		fLayout;
411 	BLayoutContext*	fLayoutContext;
412 	BObjectList<BLayoutItem> fLayoutItems;
413 	bool			fLayoutValid;
414 	bool			fMinMaxValid;
415 	bool			fLayoutInProgress;
416 	bool			fNeedsRelayout;
417 };
418 
419 
420 BView::BView(const char* name, uint32 flags, BLayout* layout)
421 	:
422 	BHandler(name)
423 {
424 	_InitData(BRect(0, 0, -1, -1), name, B_FOLLOW_NONE,
425 		flags | B_SUPPORTS_LAYOUT);
426 	SetLayout(layout);
427 }
428 
429 
430 BView::BView(BRect frame, const char* name, uint32 resizingMode, uint32 flags)
431 	:
432 	BHandler(name)
433 {
434 	_InitData(frame, name, resizingMode, flags);
435 }
436 
437 
438 BView::BView(BMessage* archive)
439 	:
440 	BHandler(BUnarchiver::PrepareArchive(archive))
441 {
442 	BUnarchiver unarchiver(archive);
443 	if (!archive)
444 		debugger("BView cannot be constructed from a NULL archive.");
445 
446 	BRect frame;
447 	archive->FindRect("_frame", &frame);
448 
449 	uint32 resizingMode;
450 	if (archive->FindInt32("_resize_mode", (int32*)&resizingMode) != B_OK)
451 		resizingMode = 0;
452 
453 	uint32 flags;
454 	if (archive->FindInt32("_flags", (int32*)&flags) != B_OK)
455 		flags = 0;
456 
457 	_InitData(frame, Name(), resizingMode, flags);
458 
459 	font_family family;
460 	font_style style;
461 	if (archive->FindString("_fname", 0, (const char**)&family) == B_OK
462 		&& archive->FindString("_fname", 1, (const char**)&style) == B_OK) {
463 		BFont font;
464 		font.SetFamilyAndStyle(family, style);
465 
466 		float size;
467 		if (archive->FindFloat("_fflt", 0, &size) == B_OK)
468 			font.SetSize(size);
469 
470 		float shear;
471 		if (archive->FindFloat("_fflt", 1, &shear) == B_OK
472 			&& shear >= 45.0 && shear <= 135.0)
473 			font.SetShear(shear);
474 
475 		float rotation;
476 		if (archive->FindFloat("_fflt", 2, &rotation) == B_OK
477 			&& rotation >=0 && rotation <= 360)
478 			font.SetRotation(rotation);
479 
480 		SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE
481 			| B_FONT_SHEAR | B_FONT_ROTATION);
482 	}
483 
484 	int32 color = 0;
485 	if (archive->FindInt32("_color", 0, &color) == B_OK)
486 		SetHighColor(get_rgb_color(color));
487 	if (archive->FindInt32("_color", 1, &color) == B_OK)
488 		SetLowColor(get_rgb_color(color));
489 	if (archive->FindInt32("_color", 2, &color) == B_OK)
490 		SetViewColor(get_rgb_color(color));
491 
492 	float tint = B_NO_TINT;
493 	if (archive->FindInt32("_uicolor", 0, &color) == B_OK
494 		&& color != B_NO_COLOR) {
495 		if (archive->FindFloat("_uitint", 0, &tint) != B_OK)
496 			tint = B_NO_TINT;
497 
498 		SetHighUIColor((color_which)color, tint);
499 	}
500 	if (archive->FindInt32("_uicolor", 1, &color) == B_OK
501 		&& color != B_NO_COLOR) {
502 		if (archive->FindFloat("_uitint", 1, &tint) != B_OK)
503 			tint = B_NO_TINT;
504 
505 		SetLowUIColor((color_which)color, tint);
506 	}
507 	if (archive->FindInt32("_uicolor", 2, &color) == B_OK
508 		&& color != B_NO_COLOR) {
509 		if (archive->FindFloat("_uitint", 2, &tint) != B_OK)
510 			tint = B_NO_TINT;
511 
512 		SetViewUIColor((color_which)color, tint);
513 	}
514 
515 	uint32 evMask;
516 	uint32 options;
517 	if (archive->FindInt32("_evmask", 0, (int32*)&evMask) == B_OK
518 		&& archive->FindInt32("_evmask", 1, (int32*)&options) == B_OK)
519 		SetEventMask(evMask, options);
520 
521 	BPoint origin;
522 	if (archive->FindPoint("_origin", &origin) == B_OK)
523 		SetOrigin(origin);
524 
525 	float scale;
526 	if (archive->FindFloat("_scale", &scale) == B_OK)
527 		SetScale(scale);
528 
529 	BAffineTransform transform;
530 	if (archive->FindFlat("_transform", &transform) == B_OK)
531 		SetTransform(transform);
532 
533 	float penSize;
534 	if (archive->FindFloat("_psize", &penSize) == B_OK)
535 		SetPenSize(penSize);
536 
537 	BPoint penLocation;
538 	if (archive->FindPoint("_ploc", &penLocation) == B_OK)
539 		MovePenTo(penLocation);
540 
541 	int16 lineCap;
542 	int16 lineJoin;
543 	float lineMiter;
544 	if (archive->FindInt16("_lmcapjoin", 0, &lineCap) == B_OK
545 		&& archive->FindInt16("_lmcapjoin", 1, &lineJoin) == B_OK
546 		&& archive->FindFloat("_lmmiter", &lineMiter) == B_OK)
547 		SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter);
548 
549 	int16 fillRule;
550 	if (archive->FindInt16("_fillrule", &fillRule) == B_OK)
551 		SetFillRule(fillRule);
552 
553 	int16 alphaBlend;
554 	int16 modeBlend;
555 	if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK
556 		&& archive->FindInt16("_blend", 1, &modeBlend) == B_OK)
557 		SetBlendingMode( (source_alpha)alphaBlend, (alpha_function)modeBlend);
558 
559 	uint32 drawingMode;
560 	if (archive->FindInt32("_dmod", (int32*)&drawingMode) == B_OK)
561 		SetDrawingMode((drawing_mode)drawingMode);
562 
563 	fLayoutData->PopulateFromArchive(archive);
564 
565 	if (archive->FindInt16("_show", &fShowLevel) != B_OK)
566 		fShowLevel = 0;
567 
568 	if (BUnarchiver::IsArchiveManaged(archive)) {
569 		int32 i = 0;
570 		while (unarchiver.EnsureUnarchived("_views", i++) == B_OK)
571 				;
572 		unarchiver.EnsureUnarchived(kLayoutField);
573 
574 	} else {
575 		BMessage msg;
576 		for (int32 i = 0; archive->FindMessage("_views", i, &msg) == B_OK;
577 			i++) {
578 			BArchivable* object = instantiate_object(&msg);
579 			if (BView* child = dynamic_cast<BView*>(object))
580 				AddChild(child);
581 		}
582 	}
583 }
584 
585 
586 BArchivable*
587 BView::Instantiate(BMessage* data)
588 {
589 	if (!validate_instantiation(data , "BView"))
590 		return NULL;
591 
592 	return new(std::nothrow) BView(data);
593 }
594 
595 
596 status_t
597 BView::Archive(BMessage* data, bool deep) const
598 {
599 	BArchiver archiver(data);
600 	status_t ret = BHandler::Archive(data, deep);
601 
602 	if (ret != B_OK)
603 		return ret;
604 
605 	if ((fState->archiving_flags & B_VIEW_FRAME_BIT) != 0)
606 		ret = data->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset));
607 
608 	if (ret == B_OK)
609 		ret = data->AddInt32("_resize_mode", ResizingMode());
610 
611 	if (ret == B_OK)
612 		ret = data->AddInt32("_flags", Flags());
613 
614 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_EVENT_MASK_BIT) != 0) {
615 		ret = data->AddInt32("_evmask", fEventMask);
616 		if (ret == B_OK)
617 			ret = data->AddInt32("_evmask", fEventOptions);
618 	}
619 
620 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_FONT_BIT) != 0) {
621 		BFont font;
622 		GetFont(&font);
623 
624 		font_family family;
625 		font_style style;
626 		font.GetFamilyAndStyle(&family, &style);
627 		ret = data->AddString("_fname", family);
628 		if (ret == B_OK)
629 			ret = data->AddString("_fname", style);
630 		if (ret == B_OK)
631 			ret = data->AddFloat("_fflt", font.Size());
632 		if (ret == B_OK)
633 			ret = data->AddFloat("_fflt", font.Shear());
634 		if (ret == B_OK)
635 			ret = data->AddFloat("_fflt", font.Rotation());
636 	}
637 
638 	// colors
639 	if (ret == B_OK)
640 		ret = data->AddInt32("_color", get_uint32_color(HighColor()));
641 	if (ret == B_OK)
642 		ret = data->AddInt32("_color", get_uint32_color(LowColor()));
643 	if (ret == B_OK)
644 		ret = data->AddInt32("_color", get_uint32_color(ViewColor()));
645 
646 	if (ret == B_OK)
647 		ret = data->AddInt32("_uicolor", (int32)HighUIColor());
648 	if (ret == B_OK)
649 		ret = data->AddInt32("_uicolor", (int32)LowUIColor());
650 	if (ret == B_OK)
651 		ret = data->AddInt32("_uicolor", (int32)ViewUIColor());
652 
653 	if (ret == B_OK)
654 		ret = data->AddFloat("_uitint", fState->which_high_color_tint);
655 	if (ret == B_OK)
656 		ret = data->AddFloat("_uitint", fState->which_low_color_tint);
657 	if (ret == B_OK)
658 		ret = data->AddFloat("_uitint", fState->which_view_color_tint);
659 
660 //	NOTE: we do not use this flag any more
661 //	if ( 1 ){
662 //		ret = data->AddInt32("_dbuf", 1);
663 //	}
664 
665 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_ORIGIN_BIT) != 0)
666 		ret = data->AddPoint("_origin", Origin());
667 
668 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_SCALE_BIT) != 0)
669 		ret = data->AddFloat("_scale", Scale());
670 
671 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_TRANSFORM_BIT) != 0) {
672 		BAffineTransform transform = Transform();
673 		ret = data->AddFlat("_transform", &transform);
674 	}
675 
676 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_PEN_SIZE_BIT) != 0)
677 		ret = data->AddFloat("_psize", PenSize());
678 
679 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_PEN_LOCATION_BIT) != 0)
680 		ret = data->AddPoint("_ploc", PenLocation());
681 
682 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_LINE_MODES_BIT) != 0) {
683 		ret = data->AddInt16("_lmcapjoin", (int16)LineCapMode());
684 		if (ret == B_OK)
685 			ret = data->AddInt16("_lmcapjoin", (int16)LineJoinMode());
686 		if (ret == B_OK)
687 			ret = data->AddFloat("_lmmiter", LineMiterLimit());
688 	}
689 
690 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_FILL_RULE_BIT) != 0)
691 		ret = data->AddInt16("_fillrule", (int16)FillRule());
692 
693 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_BLENDING_BIT) != 0) {
694 		source_alpha alphaSourceMode;
695 		alpha_function alphaFunctionMode;
696 		GetBlendingMode(&alphaSourceMode, &alphaFunctionMode);
697 
698 		ret = data->AddInt16("_blend", (int16)alphaSourceMode);
699 		if (ret == B_OK)
700 			ret = data->AddInt16("_blend", (int16)alphaFunctionMode);
701 	}
702 
703 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_DRAWING_MODE_BIT) != 0)
704 		ret = data->AddInt32("_dmod", DrawingMode());
705 
706 	if (ret == B_OK)
707 		ret = fLayoutData->AddDataToArchive(data);
708 
709 	if (ret == B_OK)
710 		ret = data->AddInt16("_show", fShowLevel);
711 
712 	if (deep && ret == B_OK) {
713 		for (BView* child = fFirstChild; child != NULL && ret == B_OK;
714 			child = child->fNextSibling)
715 			ret = archiver.AddArchivable("_views", child, deep);
716 
717 		if (ret == B_OK)
718 			ret = archiver.AddArchivable(kLayoutField, GetLayout(), deep);
719 	}
720 
721 	return archiver.Finish(ret);
722 }
723 
724 
725 status_t
726 BView::AllUnarchived(const BMessage* from)
727 {
728 	BUnarchiver unarchiver(from);
729 	status_t err = B_OK;
730 
731 	int32 count;
732 	from->GetInfo("_views", NULL, &count);
733 
734 	for (int32 i = 0; err == B_OK && i < count; i++) {
735 		BView* child;
736 		err = unarchiver.FindObject<BView>("_views", i, child);
737 		if (err == B_OK)
738 			err = _AddChild(child, NULL) ? B_OK : B_ERROR;
739 	}
740 
741 	if (err == B_OK) {
742 		BLayout*& layout = fLayoutData->fLayout;
743 		err = unarchiver.FindObject(kLayoutField, layout);
744 		if (err == B_OK && layout) {
745 			fFlags |= B_SUPPORTS_LAYOUT;
746 			fLayoutData->fLayout->SetOwner(this);
747 		}
748 	}
749 
750 	return err;
751 }
752 
753 
754 status_t
755 BView::AllArchived(BMessage* into) const
756 {
757 	return BHandler::AllArchived(into);
758 }
759 
760 
761 BView::~BView()
762 {
763 	STRACE(("BView(%s)::~BView()\n", this->Name()));
764 
765 	if (fOwner != NULL) {
766 		debugger("Trying to delete a view that belongs to a window. "
767 			"Call RemoveSelf first.");
768 	}
769 
770 	// we also delete all our children
771 
772 	BView* child = fFirstChild;
773 	while (child) {
774 		BView* nextChild = child->fNextSibling;
775 
776 		delete child;
777 		child = nextChild;
778 	}
779 
780 	SetLayout(NULL);
781 	_RemoveLayoutItemsFromLayout(true);
782 
783 	delete fLayoutData;
784 
785 	_RemoveSelf();
786 
787 	if (fToolTip != NULL)
788 		fToolTip->ReleaseReference();
789 
790 	if (fVerScroller != NULL)
791 		fVerScroller->SetTarget((BView*)NULL);
792 	if (fHorScroller != NULL)
793 		fHorScroller->SetTarget((BView*)NULL);
794 
795 	SetName(NULL);
796 
797 	_RemoveCommArray();
798 	delete fState;
799 }
800 
801 
802 BRect
803 BView::Bounds() const
804 {
805 	_CheckLock();
806 
807 	if (fIsPrinting)
808 		return fState->print_rect;
809 
810 	return fBounds;
811 }
812 
813 
814 void
815 BView::_ConvertToParent(BPoint* point, bool checkLock) const
816 {
817 	if (!fParent)
818 		return;
819 
820 	if (checkLock)
821 		_CheckLock();
822 
823 	// - our scrolling offset
824 	// + our bounds location within the parent
825 	point->x += -fBounds.left + fParentOffset.x;
826 	point->y += -fBounds.top + fParentOffset.y;
827 }
828 
829 
830 void
831 BView::ConvertToParent(BPoint* point) const
832 {
833 	_ConvertToParent(point, true);
834 }
835 
836 
837 BPoint
838 BView::ConvertToParent(BPoint point) const
839 {
840 	ConvertToParent(&point);
841 
842 	return point;
843 }
844 
845 
846 void
847 BView::_ConvertFromParent(BPoint* point, bool checkLock) const
848 {
849 	if (!fParent)
850 		return;
851 
852 	if (checkLock)
853 		_CheckLock();
854 
855 	// - our bounds location within the parent
856 	// + our scrolling offset
857 	point->x += -fParentOffset.x + fBounds.left;
858 	point->y += -fParentOffset.y + fBounds.top;
859 }
860 
861 
862 void
863 BView::ConvertFromParent(BPoint* point) const
864 {
865 	_ConvertFromParent(point, true);
866 }
867 
868 
869 BPoint
870 BView::ConvertFromParent(BPoint point) const
871 {
872 	ConvertFromParent(&point);
873 
874 	return point;
875 }
876 
877 
878 void
879 BView::ConvertToParent(BRect* rect) const
880 {
881 	if (!fParent)
882 		return;
883 
884 	_CheckLock();
885 
886 	// - our scrolling offset
887 	// + our bounds location within the parent
888 	rect->OffsetBy(-fBounds.left + fParentOffset.x,
889 		-fBounds.top + fParentOffset.y);
890 }
891 
892 
893 BRect
894 BView::ConvertToParent(BRect rect) const
895 {
896 	ConvertToParent(&rect);
897 
898 	return rect;
899 }
900 
901 
902 void
903 BView::ConvertFromParent(BRect* rect) const
904 {
905 	if (!fParent)
906 		return;
907 
908 	_CheckLock();
909 
910 	// - our bounds location within the parent
911 	// + our scrolling offset
912 	rect->OffsetBy(-fParentOffset.x + fBounds.left,
913 		-fParentOffset.y + fBounds.top);
914 }
915 
916 
917 BRect
918 BView::ConvertFromParent(BRect rect) const
919 {
920 	ConvertFromParent(&rect);
921 
922 	return rect;
923 }
924 
925 
926 void
927 BView::_ConvertToScreen(BPoint* point, bool checkLock) const
928 {
929 	if (!fParent) {
930 		if (fOwner)
931 			fOwner->ConvertToScreen(point);
932 
933 		return;
934 	}
935 
936 	if (checkLock)
937 		_CheckOwnerLock();
938 
939 	_ConvertToParent(point, false);
940 	fParent->_ConvertToScreen(point, false);
941 }
942 
943 
944 void
945 BView::ConvertToScreen(BPoint* point) const
946 {
947 	_ConvertToScreen(point, true);
948 }
949 
950 
951 BPoint
952 BView::ConvertToScreen(BPoint point) const
953 {
954 	ConvertToScreen(&point);
955 
956 	return point;
957 }
958 
959 
960 void
961 BView::_ConvertFromScreen(BPoint* point, bool checkLock) const
962 {
963 	if (!fParent) {
964 		if (fOwner)
965 			fOwner->ConvertFromScreen(point);
966 
967 		return;
968 	}
969 
970 	if (checkLock)
971 		_CheckOwnerLock();
972 
973 	_ConvertFromParent(point, false);
974 	fParent->_ConvertFromScreen(point, false);
975 }
976 
977 
978 void
979 BView::ConvertFromScreen(BPoint* point) const
980 {
981 	_ConvertFromScreen(point, true);
982 }
983 
984 
985 BPoint
986 BView::ConvertFromScreen(BPoint point) const
987 {
988 	ConvertFromScreen(&point);
989 
990 	return point;
991 }
992 
993 
994 void
995 BView::ConvertToScreen(BRect* rect) const
996 {
997 	BPoint offset(0.0, 0.0);
998 	ConvertToScreen(&offset);
999 	rect->OffsetBy(offset);
1000 }
1001 
1002 
1003 BRect
1004 BView::ConvertToScreen(BRect rect) const
1005 {
1006 	ConvertToScreen(&rect);
1007 
1008 	return rect;
1009 }
1010 
1011 
1012 void
1013 BView::ConvertFromScreen(BRect* rect) const
1014 {
1015 	BPoint offset(0.0, 0.0);
1016 	ConvertFromScreen(&offset);
1017 	rect->OffsetBy(offset);
1018 }
1019 
1020 
1021 BRect
1022 BView::ConvertFromScreen(BRect rect) const
1023 {
1024 	ConvertFromScreen(&rect);
1025 
1026 	return rect;
1027 }
1028 
1029 
1030 uint32
1031 BView::Flags() const
1032 {
1033 	_CheckLock();
1034 	return fFlags & ~_RESIZE_MASK_;
1035 }
1036 
1037 
1038 void
1039 BView::SetFlags(uint32 flags)
1040 {
1041 	if (Flags() == flags)
1042 		return;
1043 
1044 	if (fOwner) {
1045 		if (flags & B_PULSE_NEEDED) {
1046 			_CheckLock();
1047 			if (fOwner->fPulseRunner == NULL)
1048 				fOwner->SetPulseRate(fOwner->PulseRate());
1049 		}
1050 
1051 		uint32 changesFlags = flags ^ fFlags;
1052 		if (changesFlags & (B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
1053 				| B_FRAME_EVENTS | B_SUBPIXEL_PRECISE)) {
1054 			_CheckLockAndSwitchCurrent();
1055 
1056 			fOwner->fLink->StartMessage(AS_VIEW_SET_FLAGS);
1057 			fOwner->fLink->Attach<uint32>(flags);
1058 			fOwner->fLink->Flush();
1059 		}
1060 	}
1061 
1062 	/* Some useful info:
1063 		fFlags is a unsigned long (32 bits)
1064 		* bits 1-16 are used for BView's flags
1065 		* bits 17-32 are used for BView' resize mask
1066 		* _RESIZE_MASK_ is used for that. Look into View.h to see how
1067 			it's defined
1068 	*/
1069 	fFlags = (flags & ~_RESIZE_MASK_) | (fFlags & _RESIZE_MASK_);
1070 
1071 	fState->archiving_flags |= B_VIEW_FLAGS_BIT;
1072 }
1073 
1074 
1075 BRect
1076 BView::Frame() const
1077 {
1078 	return Bounds().OffsetToCopy(fParentOffset.x, fParentOffset.y);
1079 }
1080 
1081 
1082 void
1083 BView::Hide()
1084 {
1085 	if (fOwner && fShowLevel == 0) {
1086 		_CheckLockAndSwitchCurrent();
1087 		fOwner->fLink->StartMessage(AS_VIEW_HIDE);
1088 		fOwner->fLink->Flush();
1089 	}
1090 	fShowLevel++;
1091 
1092 	if (fShowLevel == 1)
1093 		_InvalidateParentLayout();
1094 }
1095 
1096 
1097 void
1098 BView::Show()
1099 {
1100 	fShowLevel--;
1101 	if (fOwner && fShowLevel == 0) {
1102 		_CheckLockAndSwitchCurrent();
1103 		fOwner->fLink->StartMessage(AS_VIEW_SHOW);
1104 		fOwner->fLink->Flush();
1105 	}
1106 
1107 	if (fShowLevel == 0)
1108 		_InvalidateParentLayout();
1109 }
1110 
1111 
1112 bool
1113 BView::IsFocus() const
1114 {
1115 	if (fOwner) {
1116 		_CheckLock();
1117 		return fOwner->CurrentFocus() == this;
1118 	} else
1119 		return false;
1120 }
1121 
1122 
1123 bool
1124 BView::IsHidden(const BView* lookingFrom) const
1125 {
1126 	if (fShowLevel > 0)
1127 		return true;
1128 
1129 	// may we be egocentric?
1130 	if (lookingFrom == this)
1131 		return false;
1132 
1133 	// we have the same visibility state as our
1134 	// parent, if there is one
1135 	if (fParent)
1136 		return fParent->IsHidden(lookingFrom);
1137 
1138 	// if we're the top view, and we're interested
1139 	// in the "global" view, we're inheriting the
1140 	// state of the window's visibility
1141 	if (fOwner && lookingFrom == NULL)
1142 		return fOwner->IsHidden();
1143 
1144 	return false;
1145 }
1146 
1147 
1148 bool
1149 BView::IsHidden() const
1150 {
1151 	return IsHidden(NULL);
1152 }
1153 
1154 
1155 bool
1156 BView::IsPrinting() const
1157 {
1158 	return fIsPrinting;
1159 }
1160 
1161 
1162 BPoint
1163 BView::LeftTop() const
1164 {
1165 	return Bounds().LeftTop();
1166 }
1167 
1168 
1169 void
1170 BView::SetResizingMode(uint32 mode)
1171 {
1172 	if (fOwner) {
1173 		_CheckLockAndSwitchCurrent();
1174 
1175 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_MODE);
1176 		fOwner->fLink->Attach<uint32>(mode);
1177 	}
1178 
1179 	// look at SetFlags() for more info on the below line
1180 	fFlags = (fFlags & ~_RESIZE_MASK_) | (mode & _RESIZE_MASK_);
1181 }
1182 
1183 
1184 uint32
1185 BView::ResizingMode() const
1186 {
1187 	return fFlags & _RESIZE_MASK_;
1188 }
1189 
1190 
1191 void
1192 BView::SetViewCursor(const BCursor* cursor, bool sync)
1193 {
1194 	if (cursor == NULL || fOwner == NULL)
1195 		return;
1196 
1197 	_CheckLock();
1198 
1199 	ViewSetViewCursorInfo info;
1200 	info.cursorToken = cursor->fServerToken;
1201 	info.viewToken = _get_object_token_(this);
1202 	info.sync = sync;
1203 
1204 	BPrivate::AppServerLink link;
1205 	link.StartMessage(AS_SET_VIEW_CURSOR);
1206 	link.Attach<ViewSetViewCursorInfo>(info);
1207 
1208 	if (sync) {
1209 		// Make sure the server has processed the message.
1210 		int32 code;
1211 		link.FlushWithReply(code);
1212 	}
1213 }
1214 
1215 
1216 void
1217 BView::Flush() const
1218 {
1219 	if (fOwner)
1220 		fOwner->Flush();
1221 }
1222 
1223 
1224 void
1225 BView::Sync() const
1226 {
1227 	_CheckOwnerLock();
1228 	if (fOwner)
1229 		fOwner->Sync();
1230 }
1231 
1232 
1233 BWindow*
1234 BView::Window() const
1235 {
1236 	return fOwner;
1237 }
1238 
1239 
1240 //	#pragma mark - Hook Functions
1241 
1242 
1243 void
1244 BView::AttachedToWindow()
1245 {
1246 	// Hook function
1247 	STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name()));
1248 }
1249 
1250 
1251 void
1252 BView::AllAttached()
1253 {
1254 	// Hook function
1255 	STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name()));
1256 }
1257 
1258 
1259 void
1260 BView::DetachedFromWindow()
1261 {
1262 	// Hook function
1263 	STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name()));
1264 }
1265 
1266 
1267 void
1268 BView::AllDetached()
1269 {
1270 	// Hook function
1271 	STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name()));
1272 }
1273 
1274 
1275 void
1276 BView::Draw(BRect updateRect)
1277 {
1278 	// Hook function
1279 	STRACE(("\tHOOK: BView(%s)::Draw()\n", Name()));
1280 }
1281 
1282 
1283 void
1284 BView::DrawAfterChildren(BRect updateRect)
1285 {
1286 	// Hook function
1287 	STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name()));
1288 }
1289 
1290 
1291 void
1292 BView::FrameMoved(BPoint newPosition)
1293 {
1294 	// Hook function
1295 	STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name()));
1296 }
1297 
1298 
1299 void
1300 BView::FrameResized(float newWidth, float newHeight)
1301 {
1302 	// Hook function
1303 	STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name()));
1304 }
1305 
1306 
1307 void
1308 BView::GetPreferredSize(float* _width, float* _height)
1309 {
1310 	STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name()));
1311 
1312 	if (_width != NULL)
1313 		*_width = fBounds.Width();
1314 	if (_height != NULL)
1315 		*_height = fBounds.Height();
1316 }
1317 
1318 
1319 void
1320 BView::ResizeToPreferred()
1321 {
1322 	STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name()));
1323 
1324 	float width;
1325 	float height;
1326 	GetPreferredSize(&width, &height);
1327 
1328 	ResizeTo(width, height);
1329 }
1330 
1331 
1332 void
1333 BView::KeyDown(const char* bytes, int32 numBytes)
1334 {
1335 	// Hook function
1336 	STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name()));
1337 
1338 	if (Window())
1339 		Window()->_KeyboardNavigation();
1340 }
1341 
1342 
1343 void
1344 BView::KeyUp(const char* bytes, int32 numBytes)
1345 {
1346 	// Hook function
1347 	STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name()));
1348 }
1349 
1350 
1351 void
1352 BView::MouseDown(BPoint where)
1353 {
1354 	// Hook function
1355 	STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name()));
1356 }
1357 
1358 
1359 void
1360 BView::MouseUp(BPoint where)
1361 {
1362 	// Hook function
1363 	STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name()));
1364 }
1365 
1366 
1367 void
1368 BView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
1369 {
1370 	// Hook function
1371 	STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name()));
1372 }
1373 
1374 
1375 void
1376 BView::Pulse()
1377 {
1378 	// Hook function
1379 	STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name()));
1380 }
1381 
1382 
1383 void
1384 BView::TargetedByScrollView(BScrollView* scroll_view)
1385 {
1386 	// Hook function
1387 	STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name()));
1388 }
1389 
1390 
1391 void
1392 BView::WindowActivated(bool active)
1393 {
1394 	// Hook function
1395 	STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name()));
1396 }
1397 
1398 
1399 //	#pragma mark - Input Functions
1400 
1401 
1402 void
1403 BView::BeginRectTracking(BRect startRect, uint32 style)
1404 {
1405 	if (_CheckOwnerLockAndSwitchCurrent()) {
1406 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_RECT_TRACK);
1407 		fOwner->fLink->Attach<BRect>(startRect);
1408 		fOwner->fLink->Attach<uint32>(style);
1409 		fOwner->fLink->Flush();
1410 	}
1411 }
1412 
1413 
1414 void
1415 BView::EndRectTracking()
1416 {
1417 	if (_CheckOwnerLockAndSwitchCurrent()) {
1418 		fOwner->fLink->StartMessage(AS_VIEW_END_RECT_TRACK);
1419 		fOwner->fLink->Flush();
1420 	}
1421 }
1422 
1423 
1424 void
1425 BView::DragMessage(BMessage* message, BRect dragRect, BHandler* replyTo)
1426 {
1427 	if (!message)
1428 		return;
1429 
1430 	_CheckOwnerLock();
1431 
1432 	// calculate the offset
1433 	BPoint offset;
1434 	uint32 buttons;
1435 	BMessage* current = fOwner->CurrentMessage();
1436 	if (!current || current->FindPoint("be:view_where", &offset) != B_OK)
1437 		GetMouse(&offset, &buttons, false);
1438 	offset -= dragRect.LeftTop();
1439 
1440 	if (!dragRect.IsValid()) {
1441 		DragMessage(message, NULL, B_OP_BLEND, offset, replyTo);
1442 		return;
1443 	}
1444 
1445 	// TODO: that's not really what should happen - the app_server should take
1446 	// the chance *NOT* to need to drag a whole bitmap around but just a frame.
1447 
1448 	// create a drag bitmap for the rect
1449 	BBitmap* bitmap = new(std::nothrow) BBitmap(dragRect, B_RGBA32);
1450 	if (bitmap == NULL)
1451 		return;
1452 
1453 	uint32* bits = (uint32*)bitmap->Bits();
1454 	uint32 bytesPerRow = bitmap->BytesPerRow();
1455 	uint32 width = dragRect.IntegerWidth() + 1;
1456 	uint32 height = dragRect.IntegerHeight() + 1;
1457 	uint32 lastRow = (height - 1) * width;
1458 
1459 	memset(bits, 0x00, height * bytesPerRow);
1460 
1461 	// top
1462 	for (uint32 i = 0; i < width; i += 2)
1463 		bits[i] = 0xff000000;
1464 
1465 	// bottom
1466 	for (uint32 i = (height % 2 == 0 ? 1 : 0); i < width; i += 2)
1467 		bits[lastRow + i] = 0xff000000;
1468 
1469 	// left
1470 	for (uint32 i = 0; i < lastRow; i += width * 2)
1471 		bits[i] = 0xff000000;
1472 
1473 	// right
1474 	for (uint32 i = (width % 2 == 0 ? width : 0); i < lastRow; i += width * 2)
1475 		bits[width - 1 + i] = 0xff000000;
1476 
1477 	DragMessage(message, bitmap, B_OP_BLEND, offset, replyTo);
1478 }
1479 
1480 
1481 void
1482 BView::DragMessage(BMessage* message, BBitmap* image, BPoint offset,
1483 	BHandler* replyTo)
1484 {
1485 	DragMessage(message, image, B_OP_COPY, offset, replyTo);
1486 }
1487 
1488 
1489 void
1490 BView::DragMessage(BMessage* message, BBitmap* image,
1491 	drawing_mode dragMode, BPoint offset, BHandler* replyTo)
1492 {
1493 	if (message == NULL)
1494 		return;
1495 
1496 	if (image == NULL) {
1497 		// TODO: workaround for drags without a bitmap - should not be necessary if
1498 		//	we move the rectangle dragging into the app_server
1499 		image = new(std::nothrow) BBitmap(BRect(0, 0, 0, 0), B_RGBA32);
1500 		if (image == NULL)
1501 			return;
1502 	}
1503 
1504 	if (replyTo == NULL)
1505 		replyTo = this;
1506 
1507 	if (replyTo->Looper() == NULL)
1508 		debugger("DragMessage: warning - the Handler needs a looper");
1509 
1510 	_CheckOwnerLock();
1511 
1512 	if (!message->HasInt32("buttons")) {
1513 		BMessage* msg = fOwner->CurrentMessage();
1514 		uint32 buttons;
1515 
1516 		if (msg == NULL
1517 			|| msg->FindInt32("buttons", (int32*)&buttons) != B_OK) {
1518 			BPoint point;
1519 			GetMouse(&point, &buttons, false);
1520 		}
1521 
1522 		message->AddInt32("buttons", buttons);
1523 	}
1524 
1525 	BMessage::Private privateMessage(message);
1526 	privateMessage.SetReply(BMessenger(replyTo, replyTo->Looper()));
1527 
1528 	int32 bufferSize = message->FlattenedSize();
1529 	char* buffer = new(std::nothrow) char[bufferSize];
1530 	if (buffer != NULL) {
1531 		message->Flatten(buffer, bufferSize);
1532 
1533 		fOwner->fLink->StartMessage(AS_VIEW_DRAG_IMAGE);
1534 		fOwner->fLink->Attach<int32>(image->_ServerToken());
1535 		fOwner->fLink->Attach<int32>((int32)dragMode);
1536 		fOwner->fLink->Attach<BPoint>(offset);
1537 		fOwner->fLink->Attach<int32>(bufferSize);
1538 		fOwner->fLink->Attach(buffer, bufferSize);
1539 
1540 		// we need to wait for the server
1541 		// to actually process this message
1542 		// before we can delete the bitmap
1543 		int32 code;
1544 		fOwner->fLink->FlushWithReply(code);
1545 
1546 		delete [] buffer;
1547 	} else {
1548 		fprintf(stderr, "BView::DragMessage() - no memory to flatten drag "
1549 			"message\n");
1550 	}
1551 
1552 	delete image;
1553 }
1554 
1555 
1556 void
1557 BView::GetMouse(BPoint* _location, uint32* _buttons, bool checkMessageQueue)
1558 {
1559 	if (_location == NULL && _buttons == NULL)
1560 		return;
1561 
1562 	_CheckOwnerLockAndSwitchCurrent();
1563 
1564 	uint32 eventOptions = fEventOptions | fMouseEventOptions;
1565 	bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
1566 	bool fullHistory = eventOptions & B_FULL_POINTER_HISTORY;
1567 
1568 	if (checkMessageQueue && !noHistory) {
1569 		Window()->UpdateIfNeeded();
1570 		BMessageQueue* queue = Window()->MessageQueue();
1571 		queue->Lock();
1572 
1573 		// Look out for mouse update messages
1574 
1575 		BMessage* message;
1576 		for (int32 i = 0; (message = queue->FindMessage(i)) != NULL; i++) {
1577 			switch (message->what) {
1578 				case B_MOUSE_MOVED:
1579 				case B_MOUSE_UP:
1580 				case B_MOUSE_DOWN:
1581 					bool deleteMessage;
1582 					if (!Window()->_StealMouseMessage(message, deleteMessage))
1583 						continue;
1584 
1585 					if (!fullHistory && message->what == B_MOUSE_MOVED) {
1586 						// Check if the message is too old. Some applications
1587 						// check the message queue in such a way that mouse
1588 						// messages *must* pile up. This check makes them work
1589 						// as intended, although these applications could simply
1590 						// use the version of BView::GetMouse() that does not
1591 						// check the history. Also note that it isn't a problem
1592 						// to delete the message in case there is not a newer
1593 						// one. If we don't find a message in the queue, we will
1594 						// just fall back to asking the app_sever directly. So
1595 						// the imposed delay will not be a problem on slower
1596 						// computers. This check also prevents another problem,
1597 						// when the message that we use is *not* removed from
1598 						// the queue. Subsequent calls to GetMouse() would find
1599 						// this message over and over!
1600 						bigtime_t eventTime;
1601 						if (message->FindInt64("when", &eventTime) == B_OK
1602 							&& system_time() - eventTime > 10000) {
1603 							// just discard the message
1604 							if (deleteMessage)
1605 								delete message;
1606 							continue;
1607 						}
1608 					}
1609 					if (_location != NULL)
1610 						message->FindPoint("screen_where", _location);
1611 					if (_buttons != NULL)
1612 						message->FindInt32("buttons", (int32*)_buttons);
1613 					queue->Unlock();
1614 						// we need to hold the queue lock until here, because
1615 						// the message might still be used for something else
1616 
1617 					if (_location != NULL)
1618 						ConvertFromScreen(_location);
1619 
1620 					if (deleteMessage)
1621 						delete message;
1622 
1623 					return;
1624 			}
1625 		}
1626 		queue->Unlock();
1627 	}
1628 
1629 	// If no mouse update message has been found in the message queue,
1630 	// we get the current mouse location and buttons from the app_server
1631 
1632 	fOwner->fLink->StartMessage(AS_GET_MOUSE);
1633 
1634 	int32 code;
1635 	if (fOwner->fLink->FlushWithReply(code) == B_OK
1636 		&& code == B_OK) {
1637 		BPoint location;
1638 		uint32 buttons;
1639 		fOwner->fLink->Read<BPoint>(&location);
1640 		fOwner->fLink->Read<uint32>(&buttons);
1641 			// TODO: ServerWindow replies with an int32 here
1642 
1643 		ConvertFromScreen(&location);
1644 			// TODO: in beos R5, location is already converted to the view
1645 			// local coordinate system, so if an app checks the window message
1646 			// queue by itself, it might not find what it expects.
1647 			// NOTE: the fact that we have mouse coords in screen space in our
1648 			// queue avoids the problem that messages already in the queue will
1649 			// be outdated as soon as a window or even the view moves. The
1650 			// second situation being quite common actually, also with regards
1651 			// to scrolling. An app reading these messages would have to know
1652 			// the locations of the window and view for each message...
1653 			// otherwise it is potentially broken anyways.
1654 		if (_location != NULL)
1655 			*_location = location;
1656 		if (_buttons != NULL)
1657 			*_buttons = buttons;
1658 	} else {
1659 		if (_location != NULL)
1660 			_location->Set(0, 0);
1661 		if (_buttons != NULL)
1662 			*_buttons = 0;
1663 	}
1664 }
1665 
1666 
1667 void
1668 BView::MakeFocus(bool focus)
1669 {
1670 	if (fOwner == NULL)
1671 		return;
1672 
1673 	// TODO: If this view has focus and focus == false,
1674 	// will there really be no other view with focus? No
1675 	// cycling to the next one?
1676 	BView* focusView = fOwner->CurrentFocus();
1677 	if (focus) {
1678 		// Unfocus a previous focus view
1679 		if (focusView != NULL && focusView != this)
1680 			focusView->MakeFocus(false);
1681 
1682 		// if we want to make this view the current focus view
1683 		fOwner->_SetFocus(this, true);
1684 	} else {
1685 		// we want to unfocus this view, but only if it actually has focus
1686 		if (focusView == this)
1687 			fOwner->_SetFocus(NULL, true);
1688 	}
1689 }
1690 
1691 
1692 BScrollBar*
1693 BView::ScrollBar(orientation direction) const
1694 {
1695 	switch (direction) {
1696 		case B_VERTICAL:
1697 			return fVerScroller;
1698 
1699 		case B_HORIZONTAL:
1700 			return fHorScroller;
1701 
1702 		default:
1703 			return NULL;
1704 	}
1705 }
1706 
1707 
1708 void
1709 BView::ScrollBy(float deltaX, float deltaY)
1710 {
1711 	ScrollTo(BPoint(fBounds.left + deltaX, fBounds.top + deltaY));
1712 }
1713 
1714 
1715 void
1716 BView::ScrollTo(BPoint where)
1717 {
1718 	// scrolling by fractional values is not supported
1719 	where.x = roundf(where.x);
1720 	where.y = roundf(where.y);
1721 
1722 	// no reason to process this further if no scroll is intended.
1723 	if (where.x == fBounds.left && where.y == fBounds.top)
1724 		return;
1725 
1726 	// make sure scrolling is within valid bounds
1727 	if (fHorScroller) {
1728 		float min, max;
1729 		fHorScroller->GetRange(&min, &max);
1730 
1731 		if (where.x < min)
1732 			where.x = min;
1733 		else if (where.x > max)
1734 			where.x = max;
1735 	}
1736 	if (fVerScroller) {
1737 		float min, max;
1738 		fVerScroller->GetRange(&min, &max);
1739 
1740 		if (where.y < min)
1741 			where.y = min;
1742 		else if (where.y > max)
1743 			where.y = max;
1744 	}
1745 
1746 	_CheckLockAndSwitchCurrent();
1747 
1748 	float xDiff = where.x - fBounds.left;
1749 	float yDiff = where.y - fBounds.top;
1750 
1751 	// if we're attached to a window tell app_server about this change
1752 	if (fOwner) {
1753 		fOwner->fLink->StartMessage(AS_VIEW_SCROLL);
1754 		fOwner->fLink->Attach<float>(xDiff);
1755 		fOwner->fLink->Attach<float>(yDiff);
1756 
1757 		fOwner->fLink->Flush();
1758 
1759 //		fState->valid_flags &= ~B_VIEW_FRAME_BIT;
1760 	}
1761 
1762 	// we modify our bounds rectangle by deltaX/deltaY coord units hor/ver.
1763 	fBounds.OffsetTo(where.x, where.y);
1764 
1765 	// then set the new values of the scrollbars
1766 	if (fHorScroller && xDiff != 0.0)
1767 		fHorScroller->SetValue(fBounds.left);
1768 	if (fVerScroller && yDiff != 0.0)
1769 		fVerScroller->SetValue(fBounds.top);
1770 
1771 }
1772 
1773 
1774 status_t
1775 BView::SetEventMask(uint32 mask, uint32 options)
1776 {
1777 	if (fEventMask == mask && fEventOptions == options)
1778 		return B_OK;
1779 
1780 	// don't change the mask if it's zero and we've got options
1781 	if (mask != 0 || options == 0)
1782 		fEventMask = mask | (fEventMask & 0xffff0000);
1783 	fEventOptions = options;
1784 
1785 	fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT;
1786 
1787 	if (fOwner) {
1788 		_CheckLockAndSwitchCurrent();
1789 
1790 		fOwner->fLink->StartMessage(AS_VIEW_SET_EVENT_MASK);
1791 		fOwner->fLink->Attach<uint32>(mask);
1792 		fOwner->fLink->Attach<uint32>(options);
1793 		fOwner->fLink->Flush();
1794 	}
1795 
1796 	return B_OK;
1797 }
1798 
1799 
1800 uint32
1801 BView::EventMask()
1802 {
1803 	return fEventMask;
1804 }
1805 
1806 
1807 status_t
1808 BView::SetMouseEventMask(uint32 mask, uint32 options)
1809 {
1810 	// Just don't do anything if the view is not yet attached
1811 	// or we were called outside of BView::MouseDown()
1812 	if (fOwner != NULL
1813 		&& fOwner->CurrentMessage() != NULL
1814 		&& fOwner->CurrentMessage()->what == B_MOUSE_DOWN) {
1815 		_CheckLockAndSwitchCurrent();
1816 		fMouseEventOptions = options;
1817 
1818 		fOwner->fLink->StartMessage(AS_VIEW_SET_MOUSE_EVENT_MASK);
1819 		fOwner->fLink->Attach<uint32>(mask);
1820 		fOwner->fLink->Attach<uint32>(options);
1821 		fOwner->fLink->Flush();
1822 		return B_OK;
1823 	}
1824 
1825 	return B_ERROR;
1826 }
1827 
1828 
1829 //	#pragma mark - Graphic State Functions
1830 
1831 
1832 void
1833 BView::PushState()
1834 {
1835 	_CheckOwnerLockAndSwitchCurrent();
1836 
1837 	fOwner->fLink->StartMessage(AS_VIEW_PUSH_STATE);
1838 
1839 	// initialize origin, scale and transform, new states start "clean".
1840 	fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT
1841 		| B_VIEW_TRANSFORM_BIT;
1842 	fState->scale = 1.0f;
1843 	fState->origin.Set(0, 0);
1844 	fState->transform.Reset();
1845 }
1846 
1847 
1848 void
1849 BView::PopState()
1850 {
1851 	_CheckOwnerLockAndSwitchCurrent();
1852 
1853 	fOwner->fLink->StartMessage(AS_VIEW_POP_STATE);
1854 	_FlushIfNotInTransaction();
1855 
1856 	// invalidate all flags (except those that are not part of pop/push)
1857 	fState->valid_flags = B_VIEW_VIEW_COLOR_BIT;
1858 }
1859 
1860 
1861 void
1862 BView::SetOrigin(BPoint where)
1863 {
1864 	SetOrigin(where.x, where.y);
1865 }
1866 
1867 
1868 void
1869 BView::SetOrigin(float x, float y)
1870 {
1871 	if (fState->IsValid(B_VIEW_ORIGIN_BIT)
1872 		&& x == fState->origin.x && y == fState->origin.y)
1873 		return;
1874 
1875 	fState->origin.x = x;
1876 	fState->origin.y = y;
1877 
1878 	if (_CheckOwnerLockAndSwitchCurrent()) {
1879 		fOwner->fLink->StartMessage(AS_VIEW_SET_ORIGIN);
1880 		fOwner->fLink->Attach<float>(x);
1881 		fOwner->fLink->Attach<float>(y);
1882 
1883 		fState->valid_flags |= B_VIEW_ORIGIN_BIT;
1884 	}
1885 
1886 	// our local coord system origin has changed, so when archiving we'll add
1887 	// this too
1888 	fState->archiving_flags |= B_VIEW_ORIGIN_BIT;
1889 }
1890 
1891 
1892 BPoint
1893 BView::Origin() const
1894 {
1895 	if (!fState->IsValid(B_VIEW_ORIGIN_BIT)) {
1896 		// we don't keep graphics state information, therefor
1897 		// we need to ask the server for the origin after PopState()
1898 		_CheckOwnerLockAndSwitchCurrent();
1899 
1900 		fOwner->fLink->StartMessage(AS_VIEW_GET_ORIGIN);
1901 
1902 		int32 code;
1903 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1904 			fOwner->fLink->Read<BPoint>(&fState->origin);
1905 
1906 		fState->valid_flags |= B_VIEW_ORIGIN_BIT;
1907 	}
1908 
1909 	return fState->origin;
1910 }
1911 
1912 
1913 void
1914 BView::SetScale(float scale) const
1915 {
1916 	if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale)
1917 		return;
1918 
1919 	if (fOwner) {
1920 		_CheckLockAndSwitchCurrent();
1921 
1922 		fOwner->fLink->StartMessage(AS_VIEW_SET_SCALE);
1923 		fOwner->fLink->Attach<float>(scale);
1924 
1925 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1926 	}
1927 
1928 	fState->scale = scale;
1929 	fState->archiving_flags |= B_VIEW_SCALE_BIT;
1930 }
1931 
1932 
1933 float
1934 BView::Scale() const
1935 {
1936 	if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) {
1937 		_CheckLockAndSwitchCurrent();
1938 
1939 		fOwner->fLink->StartMessage(AS_VIEW_GET_SCALE);
1940 
1941  		int32 code;
1942 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1943 			fOwner->fLink->Read<float>(&fState->scale);
1944 
1945 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1946 	}
1947 
1948 	return fState->scale;
1949 }
1950 
1951 
1952 void
1953 BView::SetTransform(BAffineTransform transform)
1954 {
1955 	if (fState->IsValid(B_VIEW_TRANSFORM_BIT) && transform == fState->transform)
1956 		return;
1957 
1958 	if (fOwner != NULL) {
1959 		_CheckLockAndSwitchCurrent();
1960 
1961 		fOwner->fLink->StartMessage(AS_VIEW_SET_TRANSFORM);
1962 		fOwner->fLink->Attach<BAffineTransform>(transform);
1963 
1964 		fState->valid_flags |= B_VIEW_TRANSFORM_BIT;
1965 	}
1966 
1967 	fState->transform = transform;
1968 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
1969 }
1970 
1971 
1972 BAffineTransform
1973 BView::Transform() const
1974 {
1975 	if (!fState->IsValid(B_VIEW_TRANSFORM_BIT) && fOwner != NULL) {
1976 		_CheckLockAndSwitchCurrent();
1977 
1978 		fOwner->fLink->StartMessage(AS_VIEW_GET_TRANSFORM);
1979 
1980  		int32 code;
1981 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1982 			fOwner->fLink->Read<BAffineTransform>(&fState->transform);
1983 
1984 		fState->valid_flags |= B_VIEW_TRANSFORM_BIT;
1985 	}
1986 
1987 	return fState->transform;
1988 }
1989 
1990 
1991 void
1992 BView::TranslateBy(double x, double y)
1993 {
1994 	if (fOwner != NULL) {
1995 		_CheckLockAndSwitchCurrent();
1996 
1997 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_TRANSLATE);
1998 		fOwner->fLink->Attach<double>(x);
1999 		fOwner->fLink->Attach<double>(y);
2000 
2001 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2002 	}
2003 
2004 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2005 }
2006 
2007 
2008 void
2009 BView::ScaleBy(double x, double y)
2010 {
2011 	if (fOwner != NULL) {
2012 		_CheckLockAndSwitchCurrent();
2013 
2014 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_SCALE);
2015 		fOwner->fLink->Attach<double>(x);
2016 		fOwner->fLink->Attach<double>(y);
2017 
2018 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2019 	}
2020 
2021 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2022 }
2023 
2024 
2025 void
2026 BView::RotateBy(double angleRadians)
2027 {
2028 	if (fOwner != NULL) {
2029 		_CheckLockAndSwitchCurrent();
2030 
2031 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_ROTATE);
2032 		fOwner->fLink->Attach<double>(angleRadians);
2033 
2034 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2035 	}
2036 
2037 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2038 }
2039 
2040 
2041 void
2042 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit)
2043 {
2044 	if (fState->IsValid(B_VIEW_LINE_MODES_BIT)
2045 		&& lineCap == fState->line_cap && lineJoin == fState->line_join
2046 		&& miterLimit == fState->miter_limit)
2047 		return;
2048 
2049 	if (fOwner) {
2050 		_CheckLockAndSwitchCurrent();
2051 
2052 		ViewSetLineModeInfo info;
2053 		info.lineJoin = lineJoin;
2054 		info.lineCap = lineCap;
2055 		info.miterLimit = miterLimit;
2056 
2057 		fOwner->fLink->StartMessage(AS_VIEW_SET_LINE_MODE);
2058 		fOwner->fLink->Attach<ViewSetLineModeInfo>(info);
2059 
2060 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
2061 	}
2062 
2063 	fState->line_cap = lineCap;
2064 	fState->line_join = lineJoin;
2065 	fState->miter_limit = miterLimit;
2066 
2067 	fState->archiving_flags |= B_VIEW_LINE_MODES_BIT;
2068 }
2069 
2070 
2071 join_mode
2072 BView::LineJoinMode() const
2073 {
2074 	// This will update the current state, if necessary
2075 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
2076 		LineMiterLimit();
2077 
2078 	return fState->line_join;
2079 }
2080 
2081 
2082 cap_mode
2083 BView::LineCapMode() const
2084 {
2085 	// This will update the current state, if necessary
2086 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
2087 		LineMiterLimit();
2088 
2089 	return fState->line_cap;
2090 }
2091 
2092 
2093 float
2094 BView::LineMiterLimit() const
2095 {
2096 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) {
2097 		_CheckLockAndSwitchCurrent();
2098 
2099 		fOwner->fLink->StartMessage(AS_VIEW_GET_LINE_MODE);
2100 
2101 		int32 code;
2102 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2103 
2104 			ViewSetLineModeInfo info;
2105 			fOwner->fLink->Read<ViewSetLineModeInfo>(&info);
2106 
2107 			fState->line_cap = info.lineCap;
2108 			fState->line_join = info.lineJoin;
2109 			fState->miter_limit = info.miterLimit;
2110 		}
2111 
2112 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
2113 	}
2114 
2115 	return fState->miter_limit;
2116 }
2117 
2118 
2119 void
2120 BView::SetFillRule(int32 fillRule)
2121 {
2122 	if (fState->IsValid(B_VIEW_FILL_RULE_BIT) && fillRule == fState->fill_rule)
2123 		return;
2124 
2125 	if (fOwner) {
2126 		_CheckLockAndSwitchCurrent();
2127 
2128 		fOwner->fLink->StartMessage(AS_VIEW_SET_FILL_RULE);
2129 		fOwner->fLink->Attach<int32>(fillRule);
2130 
2131 		fState->valid_flags |= B_VIEW_FILL_RULE_BIT;
2132 	}
2133 
2134 	fState->fill_rule = fillRule;
2135 
2136 	fState->archiving_flags |= B_VIEW_FILL_RULE_BIT;
2137 }
2138 
2139 
2140 int32
2141 BView::FillRule() const
2142 {
2143 	if (!fState->IsValid(B_VIEW_FILL_RULE_BIT) && fOwner) {
2144 		_CheckLockAndSwitchCurrent();
2145 
2146 		fOwner->fLink->StartMessage(AS_VIEW_GET_FILL_RULE);
2147 
2148 		int32 code;
2149 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2150 
2151 			int32 fillRule;
2152 			fOwner->fLink->Read<int32>(&fillRule);
2153 
2154 			fState->fill_rule = fillRule;
2155 		}
2156 
2157 		fState->valid_flags |= B_VIEW_FILL_RULE_BIT;
2158 	}
2159 
2160 	return fState->fill_rule;
2161 }
2162 
2163 
2164 void
2165 BView::SetDrawingMode(drawing_mode mode)
2166 {
2167 	if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT)
2168 		&& mode == fState->drawing_mode)
2169 		return;
2170 
2171 	if (fOwner) {
2172 		_CheckLockAndSwitchCurrent();
2173 
2174 		fOwner->fLink->StartMessage(AS_VIEW_SET_DRAWING_MODE);
2175 		fOwner->fLink->Attach<int8>((int8)mode);
2176 
2177 		fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
2178 	}
2179 
2180 	fState->drawing_mode = mode;
2181 	fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT;
2182 }
2183 
2184 
2185 drawing_mode
2186 BView::DrawingMode() const
2187 {
2188 	if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) {
2189 		_CheckLockAndSwitchCurrent();
2190 
2191 		fOwner->fLink->StartMessage(AS_VIEW_GET_DRAWING_MODE);
2192 
2193 		int32 code;
2194 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2195 			&& code == B_OK) {
2196 			int8 drawingMode;
2197 			fOwner->fLink->Read<int8>(&drawingMode);
2198 
2199 			fState->drawing_mode = (drawing_mode)drawingMode;
2200 			fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
2201 		}
2202 	}
2203 
2204 	return fState->drawing_mode;
2205 }
2206 
2207 
2208 void
2209 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction)
2210 {
2211 	if (fState->IsValid(B_VIEW_BLENDING_BIT)
2212 		&& sourceAlpha == fState->alpha_source_mode
2213 		&& alphaFunction == fState->alpha_function_mode)
2214 		return;
2215 
2216 	if (fOwner) {
2217 		_CheckLockAndSwitchCurrent();
2218 
2219 		ViewBlendingModeInfo info;
2220 		info.sourceAlpha = sourceAlpha;
2221 		info.alphaFunction = alphaFunction;
2222 
2223 		fOwner->fLink->StartMessage(AS_VIEW_SET_BLENDING_MODE);
2224 		fOwner->fLink->Attach<ViewBlendingModeInfo>(info);
2225 
2226 		fState->valid_flags |= B_VIEW_BLENDING_BIT;
2227 	}
2228 
2229 	fState->alpha_source_mode = sourceAlpha;
2230 	fState->alpha_function_mode = alphaFunction;
2231 
2232 	fState->archiving_flags |= B_VIEW_BLENDING_BIT;
2233 }
2234 
2235 
2236 void
2237 BView::GetBlendingMode(source_alpha* _sourceAlpha,
2238 	alpha_function* _alphaFunction) const
2239 {
2240 	if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) {
2241 		_CheckLockAndSwitchCurrent();
2242 
2243 		fOwner->fLink->StartMessage(AS_VIEW_GET_BLENDING_MODE);
2244 
2245 		int32 code;
2246  		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2247  			ViewBlendingModeInfo info;
2248 			fOwner->fLink->Read<ViewBlendingModeInfo>(&info);
2249 
2250 			fState->alpha_source_mode = info.sourceAlpha;
2251 			fState->alpha_function_mode = info.alphaFunction;
2252 
2253 			fState->valid_flags |= B_VIEW_BLENDING_BIT;
2254 		}
2255 	}
2256 
2257 	if (_sourceAlpha)
2258 		*_sourceAlpha = fState->alpha_source_mode;
2259 
2260 	if (_alphaFunction)
2261 		*_alphaFunction = fState->alpha_function_mode;
2262 }
2263 
2264 
2265 void
2266 BView::MovePenTo(BPoint point)
2267 {
2268 	MovePenTo(point.x, point.y);
2269 }
2270 
2271 
2272 void
2273 BView::MovePenTo(float x, float y)
2274 {
2275 	if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT)
2276 		&& x == fState->pen_location.x && y == fState->pen_location.y)
2277 		return;
2278 
2279 	if (fOwner) {
2280 		_CheckLockAndSwitchCurrent();
2281 
2282 		fOwner->fLink->StartMessage(AS_VIEW_SET_PEN_LOC);
2283 		fOwner->fLink->Attach<BPoint>(BPoint(x, y));
2284 
2285 		fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
2286 	}
2287 
2288 	fState->pen_location.x = x;
2289 	fState->pen_location.y = y;
2290 
2291 	fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT;
2292 }
2293 
2294 
2295 void
2296 BView::MovePenBy(float x, float y)
2297 {
2298 	// this will update the pen location if necessary
2299 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT))
2300 		PenLocation();
2301 
2302 	MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y);
2303 }
2304 
2305 
2306 BPoint
2307 BView::PenLocation() const
2308 {
2309 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) {
2310 		_CheckLockAndSwitchCurrent();
2311 
2312 		fOwner->fLink->StartMessage(AS_VIEW_GET_PEN_LOC);
2313 
2314 		int32 code;
2315 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2316 			&& code == B_OK) {
2317 			fOwner->fLink->Read<BPoint>(&fState->pen_location);
2318 
2319 			fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
2320 		}
2321 	}
2322 
2323 	return fState->pen_location;
2324 }
2325 
2326 
2327 void
2328 BView::SetPenSize(float size)
2329 {
2330 	if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size)
2331 		return;
2332 
2333 	if (fOwner) {
2334 		_CheckLockAndSwitchCurrent();
2335 
2336 		fOwner->fLink->StartMessage(AS_VIEW_SET_PEN_SIZE);
2337 		fOwner->fLink->Attach<float>(size);
2338 
2339 		fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
2340 	}
2341 
2342 	fState->pen_size = size;
2343 	fState->archiving_flags	|= B_VIEW_PEN_SIZE_BIT;
2344 }
2345 
2346 
2347 float
2348 BView::PenSize() const
2349 {
2350 	if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) {
2351 		_CheckLockAndSwitchCurrent();
2352 
2353 		fOwner->fLink->StartMessage(AS_VIEW_GET_PEN_SIZE);
2354 
2355 		int32 code;
2356 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2357 			&& code == B_OK) {
2358 			fOwner->fLink->Read<float>(&fState->pen_size);
2359 
2360 			fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
2361 		}
2362 	}
2363 
2364 	return fState->pen_size;
2365 }
2366 
2367 
2368 void
2369 BView::SetHighColor(rgb_color color)
2370 {
2371 	SetHighUIColor(B_NO_COLOR);
2372 
2373 	// are we up-to-date already?
2374 	if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT)
2375 		&& fState->high_color == color)
2376 		return;
2377 
2378 	if (fOwner) {
2379 		_CheckLockAndSwitchCurrent();
2380 
2381 		fOwner->fLink->StartMessage(AS_VIEW_SET_HIGH_COLOR);
2382 		fOwner->fLink->Attach<rgb_color>(color);
2383 
2384 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2385 	}
2386 
2387 	fState->high_color = color;
2388 
2389 	fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT;
2390 }
2391 
2392 
2393 rgb_color
2394 BView::HighColor() const
2395 {
2396 	if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) {
2397 		_CheckLockAndSwitchCurrent();
2398 
2399 		fOwner->fLink->StartMessage(AS_VIEW_GET_HIGH_COLOR);
2400 
2401 		int32 code;
2402 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2403 			&& code == B_OK) {
2404 			fOwner->fLink->Read<rgb_color>(&fState->high_color);
2405 
2406 			fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2407 		}
2408 	}
2409 
2410 	return fState->high_color;
2411 }
2412 
2413 
2414 void
2415 BView::SetHighUIColor(color_which which, float tint)
2416 {
2417 	if (fState->IsValid(B_VIEW_WHICH_HIGH_COLOR_BIT)
2418 		&& fState->which_high_color == which
2419 		&& fState->which_high_color_tint == tint)
2420 		return;
2421 
2422 	if (fOwner != NULL) {
2423 		_CheckLockAndSwitchCurrent();
2424 
2425 		fOwner->fLink->StartMessage(AS_VIEW_SET_HIGH_UI_COLOR);
2426 		fOwner->fLink->Attach<color_which>(which);
2427 		fOwner->fLink->Attach<float>(tint);
2428 
2429 		fState->valid_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2430 	}
2431 
2432 	fState->which_high_color = which;
2433 	fState->which_high_color_tint = tint;
2434 
2435 	if (which != B_NO_COLOR) {
2436 		fState->archiving_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2437 		fState->archiving_flags &= ~B_VIEW_HIGH_COLOR_BIT;
2438 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2439 
2440 		fState->high_color = tint_color(ui_color(which), tint);
2441 	} else {
2442 		fState->valid_flags &= ~B_VIEW_HIGH_COLOR_BIT;
2443 		fState->archiving_flags &= ~B_VIEW_WHICH_HIGH_COLOR_BIT;
2444 	}
2445 }
2446 
2447 
2448 color_which
2449 BView::HighUIColor(float* tint) const
2450 {
2451 	if (!fState->IsValid(B_VIEW_WHICH_HIGH_COLOR_BIT)
2452 		&& fOwner != NULL) {
2453 		_CheckLockAndSwitchCurrent();
2454 
2455 		fOwner->fLink->StartMessage(AS_VIEW_GET_HIGH_UI_COLOR);
2456 
2457 		int32 code;
2458 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2459 			&& code == B_OK) {
2460 			fOwner->fLink->Read<color_which>(&fState->which_high_color);
2461 			fOwner->fLink->Read<float>(&fState->which_high_color_tint);
2462 			fOwner->fLink->Read<rgb_color>(&fState->high_color);
2463 
2464 			fState->valid_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2465 			fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2466 		}
2467 	}
2468 
2469 	if (tint != NULL)
2470 		*tint = fState->which_high_color_tint;
2471 
2472 	return fState->which_high_color;
2473 }
2474 
2475 
2476 void
2477 BView::SetLowColor(rgb_color color)
2478 {
2479 	SetLowUIColor(B_NO_COLOR);
2480 
2481 	if (fState->IsValid(B_VIEW_LOW_COLOR_BIT)
2482 		&& fState->low_color == color)
2483 		return;
2484 
2485 	if (fOwner) {
2486 		_CheckLockAndSwitchCurrent();
2487 
2488 		fOwner->fLink->StartMessage(AS_VIEW_SET_LOW_COLOR);
2489 		fOwner->fLink->Attach<rgb_color>(color);
2490 
2491 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2492 	}
2493 
2494 	fState->low_color = color;
2495 
2496 	fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT;
2497 }
2498 
2499 
2500 rgb_color
2501 BView::LowColor() const
2502 {
2503 	if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) {
2504 		_CheckLockAndSwitchCurrent();
2505 
2506 		fOwner->fLink->StartMessage(AS_VIEW_GET_LOW_COLOR);
2507 
2508 		int32 code;
2509 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2510 			&& code == B_OK) {
2511 			fOwner->fLink->Read<rgb_color>(&fState->low_color);
2512 
2513 			fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2514 		}
2515 	}
2516 
2517 	return fState->low_color;
2518 }
2519 
2520 
2521 void
2522 BView::SetLowUIColor(color_which which, float tint)
2523 {
2524 	if (fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT)
2525 		&& fState->which_low_color == which
2526 		&& fState->which_low_color_tint == tint)
2527 		return;
2528 
2529 	if (fOwner != NULL) {
2530 		_CheckLockAndSwitchCurrent();
2531 
2532 		fOwner->fLink->StartMessage(AS_VIEW_SET_LOW_UI_COLOR);
2533 		fOwner->fLink->Attach<color_which>(which);
2534 		fOwner->fLink->Attach<float>(tint);
2535 
2536 		fState->valid_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2537 	}
2538 
2539 	fState->which_low_color = which;
2540 	fState->which_low_color_tint = tint;
2541 
2542 	if (which != B_NO_COLOR) {
2543 		fState->archiving_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2544 		fState->archiving_flags &= ~B_VIEW_LOW_COLOR_BIT;
2545 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2546 
2547 		fState->low_color = tint_color(ui_color(which), tint);
2548 	} else {
2549 		fState->valid_flags &= ~B_VIEW_LOW_COLOR_BIT;
2550 		fState->archiving_flags &= ~B_VIEW_WHICH_LOW_COLOR_BIT;
2551 	}
2552 }
2553 
2554 
2555 color_which
2556 BView::LowUIColor(float* tint) const
2557 {
2558 	if (!fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT)
2559 		&& fOwner != NULL) {
2560 		_CheckLockAndSwitchCurrent();
2561 
2562 		fOwner->fLink->StartMessage(AS_VIEW_GET_LOW_UI_COLOR);
2563 
2564 		int32 code;
2565 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2566 			&& code == B_OK) {
2567 			fOwner->fLink->Read<color_which>(&fState->which_low_color);
2568 			fOwner->fLink->Read<float>(&fState->which_low_color_tint);
2569 			fOwner->fLink->Read<rgb_color>(&fState->low_color);
2570 
2571 			fState->valid_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2572 			fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2573 		}
2574 	}
2575 
2576 	if (tint != NULL)
2577 		*tint = fState->which_low_color_tint;
2578 
2579 	return fState->which_low_color;
2580 }
2581 
2582 
2583 bool
2584 BView::HasDefaultColors() const
2585 {
2586 	// If we don't have any of these flags, then we have default colors
2587 	uint32 testMask = B_VIEW_VIEW_COLOR_BIT | B_VIEW_HIGH_COLOR_BIT
2588 		| B_VIEW_LOW_COLOR_BIT | B_VIEW_WHICH_VIEW_COLOR_BIT
2589 		| B_VIEW_WHICH_HIGH_COLOR_BIT | B_VIEW_WHICH_LOW_COLOR_BIT;
2590 
2591 	return (fState->archiving_flags & testMask) == 0;
2592 }
2593 
2594 
2595 bool
2596 BView::HasSystemColors() const
2597 {
2598 	return fState->which_view_color == B_PANEL_BACKGROUND_COLOR
2599 		&& fState->which_high_color == B_PANEL_TEXT_COLOR
2600 		&& fState->which_low_color == B_PANEL_BACKGROUND_COLOR
2601 		&& fState->which_view_color_tint == B_NO_TINT
2602 		&& fState->which_high_color_tint == B_NO_TINT
2603 		&& fState->which_low_color_tint == B_NO_TINT;
2604 }
2605 
2606 
2607 void
2608 BView::AdoptParentColors()
2609 {
2610 	AdoptViewColors(Parent());
2611 }
2612 
2613 
2614 void
2615 BView::AdoptSystemColors()
2616 {
2617 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
2618 	SetLowUIColor(B_PANEL_BACKGROUND_COLOR);
2619 	SetHighUIColor(B_PANEL_TEXT_COLOR);
2620 }
2621 
2622 
2623 void
2624 BView::AdoptViewColors(BView* view)
2625 {
2626 	if (view == NULL || (view->Window() != NULL && !view->LockLooper()))
2627 		return;
2628 
2629 	float tint = B_NO_TINT;
2630 	float viewTint = tint;
2631 	color_which viewWhich = view->ViewUIColor(&viewTint);
2632 
2633 	// View color
2634 	if (viewWhich != B_NO_COLOR)
2635 		SetViewUIColor(viewWhich, viewTint);
2636 	else
2637 		SetViewColor(view->ViewColor());
2638 
2639 	// Low color
2640 	color_which which = view->LowUIColor(&tint);
2641 	if (which != B_NO_COLOR)
2642 		SetLowUIColor(which, tint);
2643 	else if (viewWhich != B_NO_COLOR)
2644 		SetLowUIColor(viewWhich, viewTint);
2645 	else
2646 		SetLowColor(view->LowColor());
2647 
2648 	// High color
2649 	which = view->HighUIColor(&tint);
2650 	if (which != B_NO_COLOR)
2651 		SetHighUIColor(which, tint);
2652 	else
2653 		SetHighColor(view->HighColor());
2654 
2655 	if (view->Window() != NULL)
2656 		view->UnlockLooper();
2657 }
2658 
2659 
2660 void
2661 BView::SetViewColor(rgb_color color)
2662 {
2663 	SetViewUIColor(B_NO_COLOR);
2664 
2665 	if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT)
2666 		&& fState->view_color == color)
2667 		return;
2668 
2669 	if (fOwner) {
2670 		_CheckLockAndSwitchCurrent();
2671 
2672 		fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_COLOR);
2673 		fOwner->fLink->Attach<rgb_color>(color);
2674 		fOwner->fLink->Flush();
2675 
2676 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2677 	}
2678 
2679 	fState->view_color = color;
2680 
2681 	fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT;
2682 }
2683 
2684 
2685 rgb_color
2686 BView::ViewColor() const
2687 {
2688 	if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) {
2689 		_CheckLockAndSwitchCurrent();
2690 
2691 		fOwner->fLink->StartMessage(AS_VIEW_GET_VIEW_COLOR);
2692 
2693 		int32 code;
2694 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2695 			&& code == B_OK) {
2696 			fOwner->fLink->Read<rgb_color>(&fState->view_color);
2697 
2698 			fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2699 		}
2700 	}
2701 
2702 	return fState->view_color;
2703 }
2704 
2705 
2706 void
2707 BView::SetViewUIColor(color_which which, float tint)
2708 {
2709 	if (fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)
2710 		&& fState->which_view_color == which
2711 		&& fState->which_view_color_tint == tint)
2712 		return;
2713 
2714 	if (fOwner != NULL) {
2715 		_CheckLockAndSwitchCurrent();
2716 
2717 		fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_UI_COLOR);
2718 		fOwner->fLink->Attach<color_which>(which);
2719 		fOwner->fLink->Attach<float>(tint);
2720 
2721 		fState->valid_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2722 	}
2723 
2724 	fState->which_view_color = which;
2725 	fState->which_view_color_tint = tint;
2726 
2727 	if (which != B_NO_COLOR) {
2728 		fState->archiving_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2729 		fState->archiving_flags &= ~B_VIEW_VIEW_COLOR_BIT;
2730 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2731 
2732 		fState->view_color = tint_color(ui_color(which), tint);
2733 	} else {
2734 		fState->valid_flags &= ~B_VIEW_VIEW_COLOR_BIT;
2735 		fState->archiving_flags &= ~B_VIEW_WHICH_VIEW_COLOR_BIT;
2736 	}
2737 
2738 	if (!fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT))
2739 		SetLowUIColor(which, tint);
2740 }
2741 
2742 
2743 color_which
2744 BView::ViewUIColor(float* tint) const
2745 {
2746 	if (!fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)
2747 		&& fOwner != NULL) {
2748 		_CheckLockAndSwitchCurrent();
2749 
2750 		fOwner->fLink->StartMessage(AS_VIEW_GET_VIEW_UI_COLOR);
2751 
2752 		int32 code;
2753 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2754 			&& code == B_OK) {
2755 			fOwner->fLink->Read<color_which>(&fState->which_view_color);
2756 			fOwner->fLink->Read<float>(&fState->which_view_color_tint);
2757 			fOwner->fLink->Read<rgb_color>(&fState->view_color);
2758 
2759 			fState->valid_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2760 			fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2761 		}
2762 	}
2763 
2764 	if (tint != NULL)
2765 		*tint = fState->which_view_color_tint;
2766 
2767 	return fState->which_view_color;
2768 }
2769 
2770 
2771 void
2772 BView::ForceFontAliasing(bool enable)
2773 {
2774 	if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT)
2775 		&& enable == fState->font_aliasing)
2776 		return;
2777 
2778 	if (fOwner) {
2779 		_CheckLockAndSwitchCurrent();
2780 
2781 		fOwner->fLink->StartMessage(AS_VIEW_PRINT_ALIASING);
2782 		fOwner->fLink->Attach<bool>(enable);
2783 
2784 		fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT;
2785 	}
2786 
2787 	fState->font_aliasing = enable;
2788 	fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT;
2789 }
2790 
2791 
2792 void
2793 BView::SetFont(const BFont* font, uint32 mask)
2794 {
2795 	if (!font || mask == 0)
2796 		return;
2797 
2798 	if (mask == B_FONT_ALL) {
2799 		fState->font = *font;
2800 	} else {
2801 		// TODO: move this into a BFont method
2802 		if (mask & B_FONT_FAMILY_AND_STYLE)
2803 			fState->font.SetFamilyAndStyle(font->FamilyAndStyle());
2804 
2805 		if (mask & B_FONT_SIZE)
2806 			fState->font.SetSize(font->Size());
2807 
2808 		if (mask & B_FONT_SHEAR)
2809 			fState->font.SetShear(font->Shear());
2810 
2811 		if (mask & B_FONT_ROTATION)
2812 			fState->font.SetRotation(font->Rotation());
2813 
2814 		if (mask & B_FONT_FALSE_BOLD_WIDTH)
2815 			fState->font.SetFalseBoldWidth(font->FalseBoldWidth());
2816 
2817 		if (mask & B_FONT_SPACING)
2818 			fState->font.SetSpacing(font->Spacing());
2819 
2820 		if (mask & B_FONT_ENCODING)
2821 			fState->font.SetEncoding(font->Encoding());
2822 
2823 		if (mask & B_FONT_FACE)
2824 			fState->font.SetFace(font->Face());
2825 
2826 		if (mask & B_FONT_FLAGS)
2827 			fState->font.SetFlags(font->Flags());
2828 	}
2829 
2830 	fState->font_flags |= mask;
2831 
2832 	if (fOwner) {
2833 		_CheckLockAndSwitchCurrent();
2834 
2835 		fState->UpdateServerFontState(*fOwner->fLink);
2836 		fState->valid_flags |= B_VIEW_FONT_BIT;
2837 	}
2838 
2839 	fState->archiving_flags |= B_VIEW_FONT_BIT;
2840 	// TODO: InvalidateLayout() here for convenience?
2841 }
2842 
2843 
2844 void
2845 BView::GetFont(BFont* font) const
2846 {
2847 	if (!fState->IsValid(B_VIEW_FONT_BIT)) {
2848 		// we don't keep graphics state information, therefor
2849 		// we need to ask the server for the origin after PopState()
2850 		_CheckOwnerLockAndSwitchCurrent();
2851 
2852 		// TODO: add a font getter!
2853 		fState->UpdateFrom(*fOwner->fLink);
2854 	}
2855 
2856 	*font = fState->font;
2857 }
2858 
2859 
2860 void
2861 BView::GetFontHeight(font_height* height) const
2862 {
2863 	fState->font.GetHeight(height);
2864 }
2865 
2866 
2867 void
2868 BView::SetFontSize(float size)
2869 {
2870 	BFont font;
2871 	font.SetSize(size);
2872 
2873 	SetFont(&font, B_FONT_SIZE);
2874 }
2875 
2876 
2877 float
2878 BView::StringWidth(const char* string) const
2879 {
2880 	return fState->font.StringWidth(string);
2881 }
2882 
2883 
2884 float
2885 BView::StringWidth(const char* string, int32 length) const
2886 {
2887 	return fState->font.StringWidth(string, length);
2888 }
2889 
2890 
2891 void
2892 BView::GetStringWidths(char* stringArray[], int32 lengthArray[],
2893 	int32 numStrings, float widthArray[]) const
2894 {
2895 	fState->font.GetStringWidths(const_cast<const char**>(stringArray),
2896 		const_cast<const int32*>(lengthArray), numStrings, widthArray);
2897 }
2898 
2899 
2900 void
2901 BView::TruncateString(BString* string, uint32 mode, float width) const
2902 {
2903 	fState->font.TruncateString(string, mode, width);
2904 }
2905 
2906 
2907 void
2908 BView::ClipToPicture(BPicture* picture, BPoint where, bool sync)
2909 {
2910 	_ClipToPicture(picture, where, false, sync);
2911 }
2912 
2913 
2914 void
2915 BView::ClipToInversePicture(BPicture* picture, BPoint where, bool sync)
2916 {
2917 	_ClipToPicture(picture, where, true, sync);
2918 }
2919 
2920 
2921 void
2922 BView::GetClippingRegion(BRegion* region) const
2923 {
2924 	if (!region)
2925 		return;
2926 
2927 	// NOTE: the client has no idea when the clipping in the server
2928 	// changed, so it is always read from the server
2929 	region->MakeEmpty();
2930 
2931 
2932 	if (fOwner) {
2933 		if (fIsPrinting && _CheckOwnerLock()) {
2934 			region->Set(fState->print_rect);
2935 			return;
2936 		}
2937 
2938 		_CheckLockAndSwitchCurrent();
2939 		fOwner->fLink->StartMessage(AS_VIEW_GET_CLIP_REGION);
2940 
2941  		int32 code;
2942  		if (fOwner->fLink->FlushWithReply(code) == B_OK
2943  			&& code == B_OK) {
2944 			fOwner->fLink->ReadRegion(region);
2945 			fState->valid_flags |= B_VIEW_CLIP_REGION_BIT;
2946 		}
2947 	}
2948 }
2949 
2950 
2951 void
2952 BView::ConstrainClippingRegion(BRegion* region)
2953 {
2954 	if (_CheckOwnerLockAndSwitchCurrent()) {
2955 		fOwner->fLink->StartMessage(AS_VIEW_SET_CLIP_REGION);
2956 
2957 		if (region) {
2958 			int32 count = region->CountRects();
2959 			fOwner->fLink->Attach<int32>(count);
2960 			if (count > 0)
2961 				fOwner->fLink->AttachRegion(*region);
2962 		} else {
2963 			fOwner->fLink->Attach<int32>(-1);
2964 			// '-1' means that in the app_server, there won't be any 'local'
2965 			// clipping region (it will be NULL)
2966 		}
2967 
2968 		_FlushIfNotInTransaction();
2969 
2970 		fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT;
2971 		fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT;
2972 	}
2973 }
2974 
2975 
2976 void
2977 BView::ClipToRect(BRect rect)
2978 {
2979 	_ClipToRect(rect, false);
2980 }
2981 
2982 
2983 void
2984 BView::ClipToInverseRect(BRect rect)
2985 {
2986 	_ClipToRect(rect, true);
2987 }
2988 
2989 
2990 void
2991 BView::ClipToShape(BShape* shape)
2992 {
2993 	_ClipToShape(shape, false);
2994 }
2995 
2996 
2997 void
2998 BView::ClipToInverseShape(BShape* shape)
2999 {
3000 	_ClipToShape(shape, true);
3001 }
3002 
3003 
3004 //	#pragma mark - Drawing Functions
3005 
3006 
3007 void
3008 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect,
3009 	uint32 options)
3010 {
3011 	if (bitmap == NULL || fOwner == NULL
3012 		|| !bitmapRect.IsValid() || !viewRect.IsValid())
3013 		return;
3014 
3015 	_CheckLockAndSwitchCurrent();
3016 
3017 	ViewDrawBitmapInfo info;
3018 	info.bitmapToken = bitmap->_ServerToken();
3019 	info.options = options;
3020 	info.viewRect = viewRect;
3021 	info.bitmapRect = bitmapRect;
3022 
3023 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3024 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3025 
3026 	_FlushIfNotInTransaction();
3027 }
3028 
3029 
3030 void
3031 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect)
3032 {
3033 	DrawBitmapAsync(bitmap, bitmapRect, viewRect, 0);
3034 }
3035 
3036 
3037 void
3038 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect viewRect)
3039 {
3040 	if (bitmap && fOwner) {
3041 		DrawBitmapAsync(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN),
3042 			viewRect, 0);
3043 	}
3044 }
3045 
3046 
3047 void
3048 BView::DrawBitmapAsync(const BBitmap* bitmap, BPoint where)
3049 {
3050 	if (bitmap == NULL || fOwner == NULL)
3051 		return;
3052 
3053 	_CheckLockAndSwitchCurrent();
3054 
3055 	ViewDrawBitmapInfo info;
3056 	info.bitmapToken = bitmap->_ServerToken();
3057 	info.options = 0;
3058 	info.bitmapRect = bitmap->Bounds().OffsetToCopy(B_ORIGIN);
3059 	info.viewRect = info.bitmapRect.OffsetToCopy(where);
3060 
3061 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3062 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3063 
3064 	_FlushIfNotInTransaction();
3065 }
3066 
3067 
3068 void
3069 BView::DrawBitmapAsync(const BBitmap* bitmap)
3070 {
3071 	DrawBitmapAsync(bitmap, PenLocation());
3072 }
3073 
3074 
3075 void
3076 BView::DrawBitmap(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect,
3077 	uint32 options)
3078 {
3079 	if (fOwner) {
3080 		DrawBitmapAsync(bitmap, bitmapRect, viewRect, options);
3081 		Sync();
3082 	}
3083 }
3084 
3085 
3086 void
3087 BView::DrawBitmap(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect)
3088 {
3089 	if (fOwner) {
3090 		DrawBitmapAsync(bitmap, bitmapRect, viewRect, 0);
3091 		Sync();
3092 	}
3093 }
3094 
3095 
3096 void
3097 BView::DrawBitmap(const BBitmap* bitmap, BRect viewRect)
3098 {
3099 	if (bitmap && fOwner) {
3100 		DrawBitmap(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN), viewRect,
3101 			0);
3102 	}
3103 }
3104 
3105 
3106 void
3107 BView::DrawBitmap(const BBitmap* bitmap, BPoint where)
3108 {
3109 	if (fOwner) {
3110 		DrawBitmapAsync(bitmap, where);
3111 		Sync();
3112 	}
3113 }
3114 
3115 
3116 void
3117 BView::DrawBitmap(const BBitmap* bitmap)
3118 {
3119 	DrawBitmap(bitmap, PenLocation());
3120 }
3121 
3122 
3123 void
3124 BView::DrawChar(char c)
3125 {
3126 	DrawString(&c, 1, PenLocation());
3127 }
3128 
3129 
3130 void
3131 BView::DrawChar(char c, BPoint location)
3132 {
3133 	DrawString(&c, 1, location);
3134 }
3135 
3136 
3137 void
3138 BView::DrawString(const char* string, escapement_delta* delta)
3139 {
3140 	if (string == NULL)
3141 		return;
3142 
3143 	DrawString(string, strlen(string), PenLocation(), delta);
3144 }
3145 
3146 
3147 void
3148 BView::DrawString(const char* string, BPoint location, escapement_delta* delta)
3149 {
3150 	if (string == NULL)
3151 		return;
3152 
3153 	DrawString(string, strlen(string), location, delta);
3154 }
3155 
3156 
3157 void
3158 BView::DrawString(const char* string, int32 length, escapement_delta* delta)
3159 {
3160 	DrawString(string, length, PenLocation(), delta);
3161 }
3162 
3163 
3164 void
3165 BView::DrawString(const char* string, int32 length, BPoint location,
3166 	escapement_delta* delta)
3167 {
3168 	if (fOwner == NULL || string == NULL || length < 1)
3169 		return;
3170 
3171 	_CheckLockAndSwitchCurrent();
3172 
3173 	ViewDrawStringInfo info;
3174 	info.stringLength = length;
3175 	info.location = location;
3176 	if (delta != NULL)
3177 		info.delta = *delta;
3178 
3179 	// quite often delta will be NULL
3180 	if (delta)
3181 		fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_DELTA);
3182 	else
3183 		fOwner->fLink->StartMessage(AS_DRAW_STRING);
3184 
3185 	fOwner->fLink->Attach<ViewDrawStringInfo>(info);
3186 	fOwner->fLink->Attach(string, length);
3187 
3188 	_FlushIfNotInTransaction();
3189 
3190 	// this modifies our pen location, so we invalidate the flag.
3191 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3192 }
3193 
3194 
3195 void
3196 BView::DrawString(const char* string, const BPoint* locations,
3197 	int32 locationCount)
3198 {
3199 	if (string == NULL)
3200 		return;
3201 
3202 	DrawString(string, strlen(string), locations, locationCount);
3203 }
3204 
3205 
3206 void
3207 BView::DrawString(const char* string, int32 length, const BPoint* locations,
3208 	int32 locationCount)
3209 {
3210 	if (fOwner == NULL || string == NULL || length < 1 || locations == NULL)
3211 		return;
3212 
3213 	_CheckLockAndSwitchCurrent();
3214 
3215 	fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_OFFSETS);
3216 
3217 	fOwner->fLink->Attach<int32>(length);
3218 	fOwner->fLink->Attach<int32>(locationCount);
3219 	fOwner->fLink->Attach(string, length);
3220 	fOwner->fLink->Attach(locations, locationCount * sizeof(BPoint));
3221 
3222 	_FlushIfNotInTransaction();
3223 
3224 	// this modifies our pen location, so we invalidate the flag.
3225 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3226 }
3227 
3228 
3229 void
3230 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius,
3231 	::pattern pattern)
3232 {
3233 	StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius,
3234 		center.x + xRadius, center.y + yRadius), pattern);
3235 }
3236 
3237 
3238 void
3239 BView::StrokeEllipse(BRect rect, ::pattern pattern)
3240 {
3241 	if (fOwner == NULL)
3242 		return;
3243 
3244 	_CheckLockAndSwitchCurrent();
3245 	_UpdatePattern(pattern);
3246 
3247 	fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE);
3248 	fOwner->fLink->Attach<BRect>(rect);
3249 
3250 	_FlushIfNotInTransaction();
3251 }
3252 
3253 
3254 void
3255 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3256 	::pattern pattern)
3257 {
3258 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3259 		center.x + xRadius, center.y + yRadius), pattern);
3260 }
3261 
3262 
3263 void
3264 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3265 	const BGradient& gradient)
3266 {
3267 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3268 		center.x + xRadius, center.y + yRadius), gradient);
3269 }
3270 
3271 
3272 void
3273 BView::FillEllipse(BRect rect, ::pattern pattern)
3274 {
3275 	if (fOwner == NULL)
3276 		return;
3277 
3278 	_CheckLockAndSwitchCurrent();
3279 	_UpdatePattern(pattern);
3280 
3281 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE);
3282 	fOwner->fLink->Attach<BRect>(rect);
3283 
3284 	_FlushIfNotInTransaction();
3285 }
3286 
3287 
3288 void
3289 BView::FillEllipse(BRect rect, const BGradient& gradient)
3290 {
3291 	if (fOwner == NULL)
3292 		return;
3293 
3294 	_CheckLockAndSwitchCurrent();
3295 
3296 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE_GRADIENT);
3297 	fOwner->fLink->Attach<BRect>(rect);
3298 	fOwner->fLink->AttachGradient(gradient);
3299 
3300 	_FlushIfNotInTransaction();
3301 }
3302 
3303 
3304 void
3305 BView::StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle,
3306 	float arcAngle, ::pattern pattern)
3307 {
3308 	StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3309 		center.y + yRadius), startAngle, arcAngle, pattern);
3310 }
3311 
3312 
3313 void
3314 BView::StrokeArc(BRect rect, float startAngle, float arcAngle,
3315 	::pattern pattern)
3316 {
3317 	if (fOwner == NULL)
3318 		return;
3319 
3320 	_CheckLockAndSwitchCurrent();
3321 	_UpdatePattern(pattern);
3322 
3323 	fOwner->fLink->StartMessage(AS_STROKE_ARC);
3324 	fOwner->fLink->Attach<BRect>(rect);
3325 	fOwner->fLink->Attach<float>(startAngle);
3326 	fOwner->fLink->Attach<float>(arcAngle);
3327 
3328 	_FlushIfNotInTransaction();
3329 }
3330 
3331 
3332 void
3333 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3334 	float arcAngle, ::pattern pattern)
3335 {
3336 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3337 		center.y + yRadius), startAngle, arcAngle, pattern);
3338 }
3339 
3340 
3341 void
3342 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3343 	float arcAngle, const BGradient& gradient)
3344 {
3345 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3346 		center.y + yRadius), startAngle, arcAngle, gradient);
3347 }
3348 
3349 
3350 void
3351 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3352 	::pattern pattern)
3353 {
3354 	if (fOwner == NULL)
3355 		return;
3356 
3357 	_CheckLockAndSwitchCurrent();
3358 	_UpdatePattern(pattern);
3359 
3360 	fOwner->fLink->StartMessage(AS_FILL_ARC);
3361 	fOwner->fLink->Attach<BRect>(rect);
3362 	fOwner->fLink->Attach<float>(startAngle);
3363 	fOwner->fLink->Attach<float>(arcAngle);
3364 
3365 	_FlushIfNotInTransaction();
3366 }
3367 
3368 
3369 void
3370 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3371 	const BGradient& gradient)
3372 {
3373 	if (fOwner == NULL)
3374 		return;
3375 
3376 	_CheckLockAndSwitchCurrent();
3377 
3378 	fOwner->fLink->StartMessage(AS_FILL_ARC_GRADIENT);
3379 	fOwner->fLink->Attach<BRect>(rect);
3380 	fOwner->fLink->Attach<float>(startAngle);
3381 	fOwner->fLink->Attach<float>(arcAngle);
3382 	fOwner->fLink->AttachGradient(gradient);
3383 
3384 	_FlushIfNotInTransaction();
3385 }
3386 
3387 
3388 void
3389 BView::StrokeBezier(BPoint* controlPoints, ::pattern pattern)
3390 {
3391 	if (fOwner == NULL)
3392 		return;
3393 
3394 	_CheckLockAndSwitchCurrent();
3395 	_UpdatePattern(pattern);
3396 
3397 	fOwner->fLink->StartMessage(AS_STROKE_BEZIER);
3398 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3399 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3400 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3401 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3402 
3403 	_FlushIfNotInTransaction();
3404 }
3405 
3406 
3407 void
3408 BView::FillBezier(BPoint* controlPoints, ::pattern pattern)
3409 {
3410 	if (fOwner == NULL)
3411 		return;
3412 
3413 	_CheckLockAndSwitchCurrent();
3414 	_UpdatePattern(pattern);
3415 
3416 	fOwner->fLink->StartMessage(AS_FILL_BEZIER);
3417 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3418 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3419 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3420 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3421 
3422 	_FlushIfNotInTransaction();
3423 }
3424 
3425 
3426 void
3427 BView::FillBezier(BPoint* controlPoints, const BGradient& gradient)
3428 {
3429 	if (fOwner == NULL)
3430 		return;
3431 
3432 	_CheckLockAndSwitchCurrent();
3433 
3434 	fOwner->fLink->StartMessage(AS_FILL_BEZIER_GRADIENT);
3435 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3436 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3437 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3438 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3439 	fOwner->fLink->AttachGradient(gradient);
3440 
3441 	_FlushIfNotInTransaction();
3442 }
3443 
3444 
3445 void
3446 BView::StrokePolygon(const BPolygon* polygon, bool closed, ::pattern pattern)
3447 {
3448 	if (polygon == NULL)
3449 		return;
3450 
3451 	StrokePolygon(polygon->fPoints, polygon->fCount, polygon->Frame(), closed,
3452 		pattern);
3453 }
3454 
3455 
3456 void
3457 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
3458 	::pattern pattern)
3459 {
3460 	BPolygon polygon(pointArray, numPoints);
3461 
3462 	StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed,
3463 		pattern);
3464 }
3465 
3466 
3467 void
3468 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3469 	bool closed, ::pattern pattern)
3470 {
3471 	if (pointArray == NULL
3472 		|| numPoints <= 1
3473 		|| fOwner == NULL)
3474 		return;
3475 
3476 	_CheckLockAndSwitchCurrent();
3477 	_UpdatePattern(pattern);
3478 
3479 	BPolygon polygon(pointArray, numPoints);
3480 	polygon.MapTo(polygon.Frame(), bounds);
3481 
3482 	if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON,
3483 			polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool)
3484 				+ sizeof(int32)) == B_OK) {
3485 		fOwner->fLink->Attach<BRect>(polygon.Frame());
3486 		fOwner->fLink->Attach<bool>(closed);
3487 		fOwner->fLink->Attach<int32>(polygon.fCount);
3488 		fOwner->fLink->Attach(polygon.fPoints, polygon.fCount * sizeof(BPoint));
3489 
3490 		_FlushIfNotInTransaction();
3491 	} else {
3492 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3493 	}
3494 }
3495 
3496 
3497 void
3498 BView::FillPolygon(const BPolygon* polygon, ::pattern pattern)
3499 {
3500 	if (polygon == NULL
3501 		|| polygon->fCount <= 2
3502 		|| fOwner == NULL)
3503 		return;
3504 
3505 	_CheckLockAndSwitchCurrent();
3506 	_UpdatePattern(pattern);
3507 
3508 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON,
3509 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3510 				== B_OK) {
3511 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3512 		fOwner->fLink->Attach<int32>(polygon->fCount);
3513 		fOwner->fLink->Attach(polygon->fPoints,
3514 			polygon->fCount * sizeof(BPoint));
3515 
3516 		_FlushIfNotInTransaction();
3517 	} else {
3518 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3519 	}
3520 }
3521 
3522 
3523 void
3524 BView::FillPolygon(const BPolygon* polygon, const BGradient& gradient)
3525 {
3526 	if (polygon == NULL
3527 		|| polygon->fCount <= 2
3528 		|| fOwner == NULL)
3529 		return;
3530 
3531 	_CheckLockAndSwitchCurrent();
3532 
3533 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON_GRADIENT,
3534 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3535 				== B_OK) {
3536 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3537 		fOwner->fLink->Attach<int32>(polygon->fCount);
3538 		fOwner->fLink->Attach(polygon->fPoints,
3539 			polygon->fCount * sizeof(BPoint));
3540 		fOwner->fLink->AttachGradient(gradient);
3541 
3542 		_FlushIfNotInTransaction();
3543 	} else {
3544 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3545 	}
3546 }
3547 
3548 
3549 void
3550 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern)
3551 {
3552 	if (pointArray == NULL)
3553 		return;
3554 
3555 	BPolygon polygon(pointArray, numPoints);
3556 	FillPolygon(&polygon, pattern);
3557 }
3558 
3559 
3560 void
3561 BView::FillPolygon(const BPoint* pointArray, int32 numPoints,
3562 	const BGradient& gradient)
3563 {
3564 	if (pointArray == NULL)
3565 		return;
3566 
3567 	BPolygon polygon(pointArray, numPoints);
3568 	FillPolygon(&polygon, gradient);
3569 }
3570 
3571 
3572 void
3573 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3574 	::pattern pattern)
3575 {
3576 	if (pointArray == NULL)
3577 		return;
3578 
3579 	BPolygon polygon(pointArray, numPoints);
3580 
3581 	polygon.MapTo(polygon.Frame(), bounds);
3582 	FillPolygon(&polygon, pattern);
3583 }
3584 
3585 
3586 void
3587 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3588 	const BGradient& gradient)
3589 {
3590 	if (pointArray == NULL)
3591 		return;
3592 
3593 	BPolygon polygon(pointArray, numPoints);
3594 
3595 	polygon.MapTo(polygon.Frame(), bounds);
3596 	FillPolygon(&polygon, gradient);
3597 }
3598 
3599 
3600 void
3601 BView::StrokeRect(BRect rect, ::pattern pattern)
3602 {
3603 	if (fOwner == NULL)
3604 		return;
3605 
3606 	_CheckLockAndSwitchCurrent();
3607 	_UpdatePattern(pattern);
3608 
3609 	fOwner->fLink->StartMessage(AS_STROKE_RECT);
3610 	fOwner->fLink->Attach<BRect>(rect);
3611 
3612 	_FlushIfNotInTransaction();
3613 }
3614 
3615 
3616 void
3617 BView::FillRect(BRect rect, ::pattern pattern)
3618 {
3619 	if (fOwner == NULL)
3620 		return;
3621 
3622 	// NOTE: ensuring compatibility with R5,
3623 	// invalid rects are not filled, they are stroked though!
3624 	if (!rect.IsValid())
3625 		return;
3626 
3627 	_CheckLockAndSwitchCurrent();
3628 	_UpdatePattern(pattern);
3629 
3630 	fOwner->fLink->StartMessage(AS_FILL_RECT);
3631 	fOwner->fLink->Attach<BRect>(rect);
3632 
3633 	_FlushIfNotInTransaction();
3634 }
3635 
3636 
3637 void
3638 BView::FillRect(BRect rect, const BGradient& gradient)
3639 {
3640 	if (fOwner == NULL)
3641 		return;
3642 
3643 	// NOTE: ensuring compatibility with R5,
3644 	// invalid rects are not filled, they are stroked though!
3645 	if (!rect.IsValid())
3646 		return;
3647 
3648 	_CheckLockAndSwitchCurrent();
3649 
3650 	fOwner->fLink->StartMessage(AS_FILL_RECT_GRADIENT);
3651 	fOwner->fLink->Attach<BRect>(rect);
3652 	fOwner->fLink->AttachGradient(gradient);
3653 
3654 	_FlushIfNotInTransaction();
3655 }
3656 
3657 
3658 void
3659 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius,
3660 	::pattern pattern)
3661 {
3662 	if (fOwner == NULL)
3663 		return;
3664 
3665 	_CheckLockAndSwitchCurrent();
3666 	_UpdatePattern(pattern);
3667 
3668 	fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT);
3669 	fOwner->fLink->Attach<BRect>(rect);
3670 	fOwner->fLink->Attach<float>(xRadius);
3671 	fOwner->fLink->Attach<float>(yRadius);
3672 
3673 	_FlushIfNotInTransaction();
3674 }
3675 
3676 
3677 void
3678 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3679 	::pattern pattern)
3680 {
3681 	if (fOwner == NULL)
3682 		return;
3683 
3684 	_CheckLockAndSwitchCurrent();
3685 
3686 	_UpdatePattern(pattern);
3687 
3688 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT);
3689 	fOwner->fLink->Attach<BRect>(rect);
3690 	fOwner->fLink->Attach<float>(xRadius);
3691 	fOwner->fLink->Attach<float>(yRadius);
3692 
3693 	_FlushIfNotInTransaction();
3694 }
3695 
3696 
3697 void
3698 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3699 	const BGradient& gradient)
3700 {
3701 	if (fOwner == NULL)
3702 		return;
3703 
3704 	_CheckLockAndSwitchCurrent();
3705 
3706 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT_GRADIENT);
3707 	fOwner->fLink->Attach<BRect>(rect);
3708 	fOwner->fLink->Attach<float>(xRadius);
3709 	fOwner->fLink->Attach<float>(yRadius);
3710 	fOwner->fLink->AttachGradient(gradient);
3711 
3712 	_FlushIfNotInTransaction();
3713 }
3714 
3715 
3716 void
3717 BView::FillRegion(BRegion* region, ::pattern pattern)
3718 {
3719 	if (region == NULL || fOwner == NULL)
3720 		return;
3721 
3722 	_CheckLockAndSwitchCurrent();
3723 
3724 	_UpdatePattern(pattern);
3725 
3726 	fOwner->fLink->StartMessage(AS_FILL_REGION);
3727 	fOwner->fLink->AttachRegion(*region);
3728 
3729 	_FlushIfNotInTransaction();
3730 }
3731 
3732 
3733 void
3734 BView::FillRegion(BRegion* region, const BGradient& gradient)
3735 {
3736 	if (region == NULL || fOwner == NULL)
3737 		return;
3738 
3739 	_CheckLockAndSwitchCurrent();
3740 
3741 	fOwner->fLink->StartMessage(AS_FILL_REGION_GRADIENT);
3742 	fOwner->fLink->AttachRegion(*region);
3743 	fOwner->fLink->AttachGradient(gradient);
3744 
3745 	_FlushIfNotInTransaction();
3746 }
3747 
3748 
3749 void
3750 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
3751 	::pattern pattern)
3752 {
3753 	if (fOwner == NULL)
3754 		return;
3755 
3756 	_CheckLockAndSwitchCurrent();
3757 
3758 	_UpdatePattern(pattern);
3759 
3760 	fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE);
3761 	fOwner->fLink->Attach<BPoint>(point1);
3762 	fOwner->fLink->Attach<BPoint>(point2);
3763 	fOwner->fLink->Attach<BPoint>(point3);
3764 	fOwner->fLink->Attach<BRect>(bounds);
3765 
3766 	_FlushIfNotInTransaction();
3767 }
3768 
3769 
3770 void
3771 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3,
3772 	::pattern pattern)
3773 {
3774 	if (fOwner) {
3775 		// we construct the smallest rectangle that contains the 3 points
3776 		// for the 1st point
3777 		BRect bounds(point1, point1);
3778 
3779 		// for the 2nd point
3780 		if (point2.x < bounds.left)
3781 			bounds.left = point2.x;
3782 
3783 		if (point2.y < bounds.top)
3784 			bounds.top = point2.y;
3785 
3786 		if (point2.x > bounds.right)
3787 			bounds.right = point2.x;
3788 
3789 		if (point2.y > bounds.bottom)
3790 			bounds.bottom = point2.y;
3791 
3792 		// for the 3rd point
3793 		if (point3.x < bounds.left)
3794 			bounds.left = point3.x;
3795 
3796 		if (point3.y < bounds.top)
3797 			bounds.top = point3.y;
3798 
3799 		if (point3.x > bounds.right)
3800 			bounds.right = point3.x;
3801 
3802 		if (point3.y > bounds.bottom)
3803 			bounds.bottom = point3.y;
3804 
3805 		StrokeTriangle(point1, point2, point3, bounds, pattern);
3806 	}
3807 }
3808 
3809 
3810 void
3811 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3812 	::pattern pattern)
3813 {
3814 	if (fOwner) {
3815 		// we construct the smallest rectangle that contains the 3 points
3816 		// for the 1st point
3817 		BRect bounds(point1, point1);
3818 
3819 		// for the 2nd point
3820 		if (point2.x < bounds.left)
3821 			bounds.left = point2.x;
3822 
3823 		if (point2.y < bounds.top)
3824 			bounds.top = point2.y;
3825 
3826 		if (point2.x > bounds.right)
3827 			bounds.right = point2.x;
3828 
3829 		if (point2.y > bounds.bottom)
3830 			bounds.bottom = point2.y;
3831 
3832 		// for the 3rd point
3833 		if (point3.x < bounds.left)
3834 			bounds.left = point3.x;
3835 
3836 		if (point3.y < bounds.top)
3837 			bounds.top = point3.y;
3838 
3839 		if (point3.x > bounds.right)
3840 			bounds.right = point3.x;
3841 
3842 		if (point3.y > bounds.bottom)
3843 			bounds.bottom = point3.y;
3844 
3845 		FillTriangle(point1, point2, point3, bounds, pattern);
3846 	}
3847 }
3848 
3849 
3850 void
3851 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3852 	const BGradient& gradient)
3853 {
3854 	if (fOwner) {
3855 		// we construct the smallest rectangle that contains the 3 points
3856 		// for the 1st point
3857 		BRect bounds(point1, point1);
3858 
3859 		// for the 2nd point
3860 		if (point2.x < bounds.left)
3861 			bounds.left = point2.x;
3862 
3863 		if (point2.y < bounds.top)
3864 			bounds.top = point2.y;
3865 
3866 		if (point2.x > bounds.right)
3867 			bounds.right = point2.x;
3868 
3869 		if (point2.y > bounds.bottom)
3870 			bounds.bottom = point2.y;
3871 
3872 		// for the 3rd point
3873 		if (point3.x < bounds.left)
3874 			bounds.left = point3.x;
3875 
3876 		if (point3.y < bounds.top)
3877 			bounds.top = point3.y;
3878 
3879 		if (point3.x > bounds.right)
3880 			bounds.right = point3.x;
3881 
3882 		if (point3.y > bounds.bottom)
3883 			bounds.bottom = point3.y;
3884 
3885 		FillTriangle(point1, point2, point3, bounds, gradient);
3886 	}
3887 }
3888 
3889 
3890 void
3891 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3892 	BRect bounds, ::pattern pattern)
3893 {
3894 	if (fOwner == NULL)
3895 		return;
3896 
3897 	_CheckLockAndSwitchCurrent();
3898 	_UpdatePattern(pattern);
3899 
3900 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE);
3901 	fOwner->fLink->Attach<BPoint>(point1);
3902 	fOwner->fLink->Attach<BPoint>(point2);
3903 	fOwner->fLink->Attach<BPoint>(point3);
3904 	fOwner->fLink->Attach<BRect>(bounds);
3905 
3906 	_FlushIfNotInTransaction();
3907 }
3908 
3909 
3910 void
3911 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
3912 	const BGradient& gradient)
3913 {
3914 	if (fOwner == NULL)
3915 		return;
3916 
3917 	_CheckLockAndSwitchCurrent();
3918 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE_GRADIENT);
3919 	fOwner->fLink->Attach<BPoint>(point1);
3920 	fOwner->fLink->Attach<BPoint>(point2);
3921 	fOwner->fLink->Attach<BPoint>(point3);
3922 	fOwner->fLink->Attach<BRect>(bounds);
3923 	fOwner->fLink->AttachGradient(gradient);
3924 
3925 	_FlushIfNotInTransaction();
3926 }
3927 
3928 
3929 void
3930 BView::StrokeLine(BPoint toPoint, ::pattern pattern)
3931 {
3932 	StrokeLine(PenLocation(), toPoint, pattern);
3933 }
3934 
3935 
3936 void
3937 BView::StrokeLine(BPoint start, BPoint end, ::pattern pattern)
3938 {
3939 	if (fOwner == NULL)
3940 		return;
3941 
3942 	_CheckLockAndSwitchCurrent();
3943 	_UpdatePattern(pattern);
3944 
3945 	ViewStrokeLineInfo info;
3946 	info.startPoint = start;
3947 	info.endPoint = end;
3948 
3949 	fOwner->fLink->StartMessage(AS_STROKE_LINE);
3950 	fOwner->fLink->Attach<ViewStrokeLineInfo>(info);
3951 
3952 	_FlushIfNotInTransaction();
3953 
3954 	// this modifies our pen location, so we invalidate the flag.
3955 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3956 }
3957 
3958 
3959 void
3960 BView::StrokeShape(BShape* shape, ::pattern pattern)
3961 {
3962 	if (shape == NULL || fOwner == NULL)
3963 		return;
3964 
3965 	shape_data* sd = (shape_data*)shape->fPrivateData;
3966 	if (sd->opCount == 0 || sd->ptCount == 0)
3967 		return;
3968 
3969 	_CheckLockAndSwitchCurrent();
3970 	_UpdatePattern(pattern);
3971 
3972 	fOwner->fLink->StartMessage(AS_STROKE_SHAPE);
3973 	fOwner->fLink->Attach<BRect>(shape->Bounds());
3974 	fOwner->fLink->Attach<int32>(sd->opCount);
3975 	fOwner->fLink->Attach<int32>(sd->ptCount);
3976 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32));
3977 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
3978 
3979 	_FlushIfNotInTransaction();
3980 }
3981 
3982 
3983 void
3984 BView::FillShape(BShape* shape, ::pattern pattern)
3985 {
3986 	if (shape == NULL || fOwner == NULL)
3987 		return;
3988 
3989 	shape_data* sd = (shape_data*)(shape->fPrivateData);
3990 	if (sd->opCount == 0 || sd->ptCount == 0)
3991 		return;
3992 
3993 	_CheckLockAndSwitchCurrent();
3994 	_UpdatePattern(pattern);
3995 
3996 	fOwner->fLink->StartMessage(AS_FILL_SHAPE);
3997 	fOwner->fLink->Attach<BRect>(shape->Bounds());
3998 	fOwner->fLink->Attach<int32>(sd->opCount);
3999 	fOwner->fLink->Attach<int32>(sd->ptCount);
4000 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32));
4001 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
4002 
4003 	_FlushIfNotInTransaction();
4004 }
4005 
4006 
4007 void
4008 BView::FillShape(BShape* shape, const BGradient& gradient)
4009 {
4010 	if (shape == NULL || fOwner == NULL)
4011 		return;
4012 
4013 	shape_data* sd = (shape_data*)(shape->fPrivateData);
4014 	if (sd->opCount == 0 || sd->ptCount == 0)
4015 		return;
4016 
4017 	_CheckLockAndSwitchCurrent();
4018 
4019 	fOwner->fLink->StartMessage(AS_FILL_SHAPE_GRADIENT);
4020 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4021 	fOwner->fLink->Attach<int32>(sd->opCount);
4022 	fOwner->fLink->Attach<int32>(sd->ptCount);
4023 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32));
4024 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
4025 	fOwner->fLink->AttachGradient(gradient);
4026 
4027 	_FlushIfNotInTransaction();
4028 }
4029 
4030 
4031 void
4032 BView::BeginLineArray(int32 count)
4033 {
4034 	if (fOwner == NULL)
4035 		return;
4036 
4037 	if (count <= 0)
4038 		debugger("Calling BeginLineArray with a count <= 0");
4039 
4040 	_CheckLock();
4041 
4042 	if (fCommArray) {
4043 		debugger("Can't nest BeginLineArray calls");
4044 			// not fatal, but it helps during
4045 			// development of your app and is in
4046 			// line with R5...
4047 		delete[] fCommArray->array;
4048 		delete fCommArray;
4049 	}
4050 
4051 	// TODO: since this method cannot return failure, and further AddLine()
4052 	//	calls with a NULL fCommArray would drop into the debugger anyway,
4053 	//	we allow the possible std::bad_alloc exceptions here...
4054 	fCommArray = new _array_data_;
4055 	fCommArray->count = 0;
4056 
4057 	// Make sure the fCommArray is initialized to reasonable values in cases of
4058 	// bad_alloc. At least the exception can be caught and EndLineArray won't
4059 	// crash.
4060 	fCommArray->array = NULL;
4061 	fCommArray->maxCount = 0;
4062 
4063 	fCommArray->array = new ViewLineArrayInfo[count];
4064 	fCommArray->maxCount = count;
4065 }
4066 
4067 
4068 void
4069 BView::AddLine(BPoint start, BPoint end, rgb_color color)
4070 {
4071 	if (fOwner == NULL)
4072 		return;
4073 
4074 	if (!fCommArray)
4075 		debugger("BeginLineArray must be called before using AddLine");
4076 
4077 	_CheckLock();
4078 
4079 	const uint32 &arrayCount = fCommArray->count;
4080 	if (arrayCount < fCommArray->maxCount) {
4081 		fCommArray->array[arrayCount].startPoint = start;
4082 		fCommArray->array[arrayCount].endPoint = end;
4083 		fCommArray->array[arrayCount].color = color;
4084 
4085 		fCommArray->count++;
4086 	}
4087 }
4088 
4089 
4090 void
4091 BView::EndLineArray()
4092 {
4093 	if (fOwner == NULL)
4094 		return;
4095 
4096 	if (fCommArray == NULL)
4097 		debugger("Can't call EndLineArray before BeginLineArray");
4098 
4099 	_CheckLockAndSwitchCurrent();
4100 
4101 	fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY);
4102 	fOwner->fLink->Attach<int32>(fCommArray->count);
4103 	fOwner->fLink->Attach(fCommArray->array,
4104 		fCommArray->count * sizeof(ViewLineArrayInfo));
4105 
4106 	_FlushIfNotInTransaction();
4107 
4108 	_RemoveCommArray();
4109 }
4110 
4111 
4112 void
4113 BView::SetDiskMode(char* filename, long offset)
4114 {
4115 	// TODO: implement
4116 	// One BeBook version has this to say about SetDiskMode():
4117 	//
4118 	// "Begins recording a picture to the file with the given filename
4119 	// at the given offset. Subsequent drawing commands sent to the view
4120 	// will be written to the file until EndPicture() is called. The
4121 	// stored commands may be played from the file with DrawPicture()."
4122 }
4123 
4124 
4125 void
4126 BView::BeginPicture(BPicture* picture)
4127 {
4128 	if (_CheckOwnerLockAndSwitchCurrent()
4129 		&& picture && picture->fUsurped == NULL) {
4130 		picture->Usurp(fCurrentPicture);
4131 		fCurrentPicture = picture;
4132 
4133 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_PICTURE);
4134 	}
4135 }
4136 
4137 
4138 void
4139 BView::AppendToPicture(BPicture* picture)
4140 {
4141 	_CheckLockAndSwitchCurrent();
4142 
4143 	if (picture && picture->fUsurped == NULL) {
4144 		int32 token = picture->Token();
4145 
4146 		if (token == -1) {
4147 			BeginPicture(picture);
4148 		} else {
4149 			picture->SetToken(-1);
4150 			picture->Usurp(fCurrentPicture);
4151 			fCurrentPicture = picture;
4152 			fOwner->fLink->StartMessage(AS_VIEW_APPEND_TO_PICTURE);
4153 			fOwner->fLink->Attach<int32>(token);
4154 		}
4155 	}
4156 }
4157 
4158 
4159 BPicture*
4160 BView::EndPicture()
4161 {
4162 	if (_CheckOwnerLockAndSwitchCurrent() && fCurrentPicture) {
4163 		int32 token;
4164 
4165 		fOwner->fLink->StartMessage(AS_VIEW_END_PICTURE);
4166 
4167 		int32 code;
4168 		if (fOwner->fLink->FlushWithReply(code) == B_OK
4169 			&& code == B_OK
4170 			&& fOwner->fLink->Read<int32>(&token) == B_OK) {
4171 			BPicture* picture = fCurrentPicture;
4172 			fCurrentPicture = picture->StepDown();
4173 			picture->SetToken(token);
4174 
4175 			// TODO do this more efficient e.g. use a shared area and let the
4176 			// client write into it
4177 			picture->_Download();
4178 			return picture;
4179 		}
4180 	}
4181 
4182 	return NULL;
4183 }
4184 
4185 
4186 void
4187 BView::SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
4188 	uint32 followFlags, uint32 options)
4189 {
4190 	_SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options);
4191 }
4192 
4193 
4194 void
4195 BView::SetViewBitmap(const BBitmap* bitmap, uint32 followFlags, uint32 options)
4196 {
4197 	BRect rect;
4198  	if (bitmap)
4199 		rect = bitmap->Bounds();
4200 
4201  	rect.OffsetTo(B_ORIGIN);
4202 
4203 	_SetViewBitmap(bitmap, rect, rect, followFlags, options);
4204 }
4205 
4206 
4207 void
4208 BView::ClearViewBitmap()
4209 {
4210 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4211 }
4212 
4213 
4214 status_t
4215 BView::SetViewOverlay(const BBitmap* overlay, BRect srcRect, BRect dstRect,
4216 	rgb_color* colorKey, uint32 followFlags, uint32 options)
4217 {
4218 	if (overlay == NULL || (overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0)
4219 		return B_BAD_VALUE;
4220 
4221 	status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags,
4222 		options | AS_REQUEST_COLOR_KEY);
4223 	if (status == B_OK) {
4224 		// read the color that will be treated as transparent
4225 		fOwner->fLink->Read<rgb_color>(colorKey);
4226 	}
4227 
4228 	return status;
4229 }
4230 
4231 
4232 status_t
4233 BView::SetViewOverlay(const BBitmap* overlay, rgb_color* colorKey,
4234 	uint32 followFlags, uint32 options)
4235 {
4236 	if (overlay == NULL)
4237 		return B_BAD_VALUE;
4238 
4239 	BRect rect = overlay->Bounds();
4240  	rect.OffsetTo(B_ORIGIN);
4241 
4242 	return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options);
4243 }
4244 
4245 
4246 void
4247 BView::ClearViewOverlay()
4248 {
4249 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4250 }
4251 
4252 
4253 void
4254 BView::CopyBits(BRect src, BRect dst)
4255 {
4256 	if (fOwner == NULL)
4257 		return;
4258 
4259 	if (!src.IsValid() || !dst.IsValid())
4260 		return;
4261 
4262 	_CheckLockAndSwitchCurrent();
4263 
4264 	fOwner->fLink->StartMessage(AS_VIEW_COPY_BITS);
4265 	fOwner->fLink->Attach<BRect>(src);
4266 	fOwner->fLink->Attach<BRect>(dst);
4267 
4268 	_FlushIfNotInTransaction();
4269 }
4270 
4271 
4272 void
4273 BView::DrawPicture(const BPicture* picture)
4274 {
4275 	if (picture == NULL)
4276 		return;
4277 
4278 	DrawPictureAsync(picture, PenLocation());
4279 	Sync();
4280 }
4281 
4282 
4283 void
4284 BView::DrawPicture(const BPicture* picture, BPoint where)
4285 {
4286 	if (picture == NULL)
4287 		return;
4288 
4289 	DrawPictureAsync(picture, where);
4290 	Sync();
4291 }
4292 
4293 
4294 void
4295 BView::DrawPicture(const char* filename, long offset, BPoint where)
4296 {
4297 	if (!filename)
4298 		return;
4299 
4300 	DrawPictureAsync(filename, offset, where);
4301 	Sync();
4302 }
4303 
4304 
4305 void
4306 BView::DrawPictureAsync(const BPicture* picture)
4307 {
4308 	if (picture == NULL)
4309 		return;
4310 
4311 	DrawPictureAsync(picture, PenLocation());
4312 }
4313 
4314 
4315 void
4316 BView::DrawPictureAsync(const BPicture* picture, BPoint where)
4317 {
4318 	if (picture == NULL)
4319 		return;
4320 
4321 	if (_CheckOwnerLockAndSwitchCurrent() && picture->Token() > 0) {
4322 		fOwner->fLink->StartMessage(AS_VIEW_DRAW_PICTURE);
4323 		fOwner->fLink->Attach<int32>(picture->Token());
4324 		fOwner->fLink->Attach<BPoint>(where);
4325 
4326 		_FlushIfNotInTransaction();
4327 	}
4328 }
4329 
4330 
4331 void
4332 BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
4333 {
4334 	if (!filename)
4335 		return;
4336 
4337 	// TODO: Test
4338 	BFile file(filename, B_READ_ONLY);
4339 	if (file.InitCheck() < B_OK)
4340 		return;
4341 
4342 	file.Seek(offset, SEEK_SET);
4343 
4344 	BPicture picture;
4345 	if (picture.Unflatten(&file) < B_OK)
4346 		return;
4347 
4348 	DrawPictureAsync(&picture, where);
4349 }
4350 
4351 
4352 void
4353 BView::BeginLayer(uint8 opacity)
4354 {
4355 	if (_CheckOwnerLockAndSwitchCurrent()) {
4356 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_LAYER);
4357 		fOwner->fLink->Attach<uint8>(opacity);
4358 		_FlushIfNotInTransaction();
4359 	}
4360 }
4361 
4362 
4363 void
4364 BView::EndLayer()
4365 {
4366 	if (_CheckOwnerLockAndSwitchCurrent()) {
4367 		fOwner->fLink->StartMessage(AS_VIEW_END_LAYER);
4368 		_FlushIfNotInTransaction();
4369 	}
4370 }
4371 
4372 
4373 void
4374 BView::Invalidate(BRect invalRect)
4375 {
4376 	if (fOwner == NULL)
4377 		return;
4378 
4379 	// NOTE: This rounding of the invalid rect is to stay compatible with BeOS.
4380 	// On the server side, the invalid rect will be converted to a BRegion,
4381 	// which rounds in a different manner, so that it really includes the
4382 	// fractional coordinates of a BRect (ie ceilf(rect.right) &
4383 	// ceilf(rect.bottom)), which is also what BeOS does. So we have to do the
4384 	// different rounding here to stay compatible in both ways.
4385 	invalRect.left = (int)invalRect.left;
4386 	invalRect.top = (int)invalRect.top;
4387 	invalRect.right = (int)invalRect.right;
4388 	invalRect.bottom = (int)invalRect.bottom;
4389 	if (!invalRect.IsValid())
4390 		return;
4391 
4392 	_CheckLockAndSwitchCurrent();
4393 
4394 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_RECT);
4395 	fOwner->fLink->Attach<BRect>(invalRect);
4396 
4397 // TODO: determine why this check isn't working correctly.
4398 #if 0
4399 	if (!fOwner->fUpdateRequested) {
4400 		fOwner->fLink->Flush();
4401 		fOwner->fUpdateRequested = true;
4402 	}
4403 #else
4404 	fOwner->fLink->Flush();
4405 #endif
4406 }
4407 
4408 
4409 void
4410 BView::Invalidate(const BRegion* region)
4411 {
4412 	if (region == NULL || fOwner == NULL)
4413 		return;
4414 
4415 	_CheckLockAndSwitchCurrent();
4416 
4417 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_REGION);
4418 	fOwner->fLink->AttachRegion(*region);
4419 
4420 // TODO: See above.
4421 #if 0
4422 	if (!fOwner->fUpdateRequested) {
4423 		fOwner->fLink->Flush();
4424 		fOwner->fUpdateRequested = true;
4425 	}
4426 #else
4427 	fOwner->fLink->Flush();
4428 #endif
4429 }
4430 
4431 
4432 void
4433 BView::Invalidate()
4434 {
4435 	Invalidate(Bounds());
4436 }
4437 
4438 
4439 void
4440 BView::DelayedInvalidate(bigtime_t delay)
4441 {
4442 	DelayedInvalidate(delay, Bounds());
4443 }
4444 
4445 
4446 void
4447 BView::DelayedInvalidate(bigtime_t delay, BRect invalRect)
4448 {
4449 	if (fOwner == NULL)
4450 		return;
4451 
4452 	invalRect.left = (int)invalRect.left;
4453 	invalRect.top = (int)invalRect.top;
4454 	invalRect.right = (int)invalRect.right;
4455 	invalRect.bottom = (int)invalRect.bottom;
4456 	if (!invalRect.IsValid())
4457 		return;
4458 
4459 	_CheckLockAndSwitchCurrent();
4460 
4461 	fOwner->fLink->StartMessage(AS_VIEW_DELAYED_INVALIDATE_RECT);
4462 	fOwner->fLink->Attach<bigtime_t>(system_time() + delay);
4463 	fOwner->fLink->Attach<BRect>(invalRect);
4464 	fOwner->fLink->Flush();
4465 }
4466 
4467 
4468 void
4469 BView::InvertRect(BRect rect)
4470 {
4471 	if (fOwner) {
4472 		_CheckLockAndSwitchCurrent();
4473 
4474 		fOwner->fLink->StartMessage(AS_VIEW_INVERT_RECT);
4475 		fOwner->fLink->Attach<BRect>(rect);
4476 
4477 		_FlushIfNotInTransaction();
4478 	}
4479 }
4480 
4481 
4482 //	#pragma mark - View Hierarchy Functions
4483 
4484 
4485 void
4486 BView::AddChild(BView* child, BView* before)
4487 {
4488 	STRACE(("BView(%s)::AddChild(child '%s', before '%s')\n",
4489 		this->Name(),
4490 		child != NULL && child->Name() ? child->Name() : "NULL",
4491 		before != NULL && before->Name() ? before->Name() : "NULL"));
4492 
4493 	if (!_AddChild(child, before))
4494 		return;
4495 
4496 	if (fLayoutData->fLayout)
4497 		fLayoutData->fLayout->AddView(child);
4498 }
4499 
4500 
4501 bool
4502 BView::AddChild(BLayoutItem* child)
4503 {
4504 	if (!fLayoutData->fLayout)
4505 		return false;
4506 	return fLayoutData->fLayout->AddItem(child);
4507 }
4508 
4509 
4510 bool
4511 BView::_AddChild(BView* child, BView* before)
4512 {
4513 	if (!child)
4514 		return false;
4515 
4516 	if (child->fParent != NULL) {
4517 		debugger("AddChild failed - the view already has a parent.");
4518 		return false;
4519 	}
4520 
4521 	if (child == this) {
4522 		debugger("AddChild failed - cannot add a view to itself.");
4523 		return false;
4524 	}
4525 
4526 	bool lockedOwner = false;
4527 	if (fOwner && !fOwner->IsLocked()) {
4528 		fOwner->Lock();
4529 		lockedOwner = true;
4530 	}
4531 
4532 	if (!_AddChildToList(child, before)) {
4533 		debugger("AddChild failed!");
4534 		if (lockedOwner)
4535 			fOwner->Unlock();
4536 		return false;
4537 	}
4538 
4539 	if (fOwner) {
4540 		_CheckLockAndSwitchCurrent();
4541 
4542 		child->_SetOwner(fOwner);
4543 		child->_CreateSelf();
4544 		child->_Attach();
4545 
4546 		if (lockedOwner)
4547 			fOwner->Unlock();
4548 	}
4549 
4550 	InvalidateLayout();
4551 
4552 	return true;
4553 }
4554 
4555 
4556 bool
4557 BView::RemoveChild(BView* child)
4558 {
4559 	STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name()));
4560 
4561 	if (!child)
4562 		return false;
4563 
4564 	if (child->fParent != this)
4565 		return false;
4566 
4567 	return child->RemoveSelf();
4568 }
4569 
4570 
4571 int32
4572 BView::CountChildren() const
4573 {
4574 	_CheckLock();
4575 
4576 	uint32 count = 0;
4577 	BView* child = fFirstChild;
4578 
4579 	while (child != NULL) {
4580 		count++;
4581 		child = child->fNextSibling;
4582 	}
4583 
4584 	return count;
4585 }
4586 
4587 
4588 BView*
4589 BView::ChildAt(int32 index) const
4590 {
4591 	_CheckLock();
4592 
4593 	BView* child = fFirstChild;
4594 	while (child != NULL && index-- > 0) {
4595 		child = child->fNextSibling;
4596 	}
4597 
4598 	return child;
4599 }
4600 
4601 
4602 BView*
4603 BView::NextSibling() const
4604 {
4605 	return fNextSibling;
4606 }
4607 
4608 
4609 BView*
4610 BView::PreviousSibling() const
4611 {
4612 	return fPreviousSibling;
4613 }
4614 
4615 
4616 bool
4617 BView::RemoveSelf()
4618 {
4619 	_RemoveLayoutItemsFromLayout(false);
4620 
4621 	return _RemoveSelf();
4622 }
4623 
4624 
4625 bool
4626 BView::_RemoveSelf()
4627 {
4628 	STRACE(("BView(%s)::_RemoveSelf()\n", Name()));
4629 
4630 	// Remove this child from its parent
4631 
4632 	BWindow* owner = fOwner;
4633 	_CheckLock();
4634 
4635 	if (owner != NULL) {
4636 		_UpdateStateForRemove();
4637 		_Detach();
4638 	}
4639 
4640 	BView* parent = fParent;
4641 	if (!parent || !parent->_RemoveChildFromList(this))
4642 		return false;
4643 
4644 	if (owner != NULL && !fTopLevelView) {
4645 		// the top level view is deleted by the app_server automatically
4646 		owner->fLink->StartMessage(AS_VIEW_DELETE);
4647 		owner->fLink->Attach<int32>(_get_object_token_(this));
4648 	}
4649 
4650 	parent->InvalidateLayout();
4651 
4652 	STRACE(("DONE: BView(%s)::_RemoveSelf()\n", Name()));
4653 
4654 	return true;
4655 }
4656 
4657 
4658 void
4659 BView::_RemoveLayoutItemsFromLayout(bool deleteItems)
4660 {
4661 	if (fParent == NULL || fParent->fLayoutData->fLayout == NULL)
4662 		return;
4663 
4664 	int32 index = fLayoutData->fLayoutItems.CountItems();
4665 	while (index-- > 0) {
4666 		BLayoutItem* item = fLayoutData->fLayoutItems.ItemAt(index);
4667 		item->RemoveSelf();
4668 			// Removes item from fLayoutItems list
4669 		if (deleteItems)
4670 			delete item;
4671 	}
4672 }
4673 
4674 
4675 BView*
4676 BView::Parent() const
4677 {
4678 	if (fParent && fParent->fTopLevelView)
4679 		return NULL;
4680 
4681 	return fParent;
4682 }
4683 
4684 
4685 BView*
4686 BView::FindView(const char* name) const
4687 {
4688 	if (name == NULL)
4689 		return NULL;
4690 
4691 	if (Name() != NULL && !strcmp(Name(), name))
4692 		return const_cast<BView*>(this);
4693 
4694 	BView* child = fFirstChild;
4695 	while (child != NULL) {
4696 		BView* view = child->FindView(name);
4697 		if (view != NULL)
4698 			return view;
4699 
4700 		child = child->fNextSibling;
4701 	}
4702 
4703 	return NULL;
4704 }
4705 
4706 
4707 void
4708 BView::MoveBy(float deltaX, float deltaY)
4709 {
4710 	MoveTo(fParentOffset.x + roundf(deltaX), fParentOffset.y + roundf(deltaY));
4711 }
4712 
4713 
4714 void
4715 BView::MoveTo(BPoint where)
4716 {
4717 	MoveTo(where.x, where.y);
4718 }
4719 
4720 
4721 void
4722 BView::MoveTo(float x, float y)
4723 {
4724 	if (x == fParentOffset.x && y == fParentOffset.y)
4725 		return;
4726 
4727 	// BeBook says we should do this. And it makes sense.
4728 	x = roundf(x);
4729 	y = roundf(y);
4730 
4731 	if (fOwner) {
4732 		_CheckLockAndSwitchCurrent();
4733 		fOwner->fLink->StartMessage(AS_VIEW_MOVE_TO);
4734 		fOwner->fLink->Attach<float>(x);
4735 		fOwner->fLink->Attach<float>(y);
4736 
4737 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4738 
4739 		_FlushIfNotInTransaction();
4740 	}
4741 
4742 	_MoveTo((int32)x, (int32)y);
4743 }
4744 
4745 
4746 void
4747 BView::ResizeBy(float deltaWidth, float deltaHeight)
4748 {
4749 	// BeBook says we should do this. And it makes sense.
4750 	deltaWidth = roundf(deltaWidth);
4751 	deltaHeight = roundf(deltaHeight);
4752 
4753 	if (deltaWidth == 0 && deltaHeight == 0)
4754 		return;
4755 
4756 	if (fOwner) {
4757 		_CheckLockAndSwitchCurrent();
4758 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_TO);
4759 
4760 		fOwner->fLink->Attach<float>(fBounds.Width() + deltaWidth);
4761 		fOwner->fLink->Attach<float>(fBounds.Height() + deltaHeight);
4762 
4763 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4764 
4765 		_FlushIfNotInTransaction();
4766 	}
4767 
4768 	_ResizeBy((int32)deltaWidth, (int32)deltaHeight);
4769 }
4770 
4771 
4772 void
4773 BView::ResizeTo(float width, float height)
4774 {
4775 	ResizeBy(width - fBounds.Width(), height - fBounds.Height());
4776 }
4777 
4778 
4779 void
4780 BView::ResizeTo(BSize size)
4781 {
4782 	ResizeBy(size.width - fBounds.Width(), size.height - fBounds.Height());
4783 }
4784 
4785 
4786 //	#pragma mark - Inherited Methods (from BHandler)
4787 
4788 
4789 status_t
4790 BView::GetSupportedSuites(BMessage* data)
4791 {
4792 	if (data == NULL)
4793 		return B_BAD_VALUE;
4794 
4795 	status_t status = data->AddString("suites", "suite/vnd.Be-view");
4796 	BPropertyInfo propertyInfo(sViewPropInfo);
4797 	if (status == B_OK)
4798 		status = data->AddFlat("messages", &propertyInfo);
4799 	if (status == B_OK)
4800 		return BHandler::GetSupportedSuites(data);
4801 	return status;
4802 }
4803 
4804 
4805 BHandler*
4806 BView::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
4807 	int32 what, const char* property)
4808 {
4809 	if (message->what == B_WINDOW_MOVE_BY
4810 		|| message->what == B_WINDOW_MOVE_TO) {
4811 		return this;
4812 	}
4813 
4814 	BPropertyInfo propertyInfo(sViewPropInfo);
4815 	status_t err = B_BAD_SCRIPT_SYNTAX;
4816 	BMessage replyMsg(B_REPLY);
4817 
4818 	switch (propertyInfo.FindMatch(message, index, specifier, what, property)) {
4819 		case 0:
4820 		case 1:
4821 		case 3:
4822 			return this;
4823 
4824 		case 2:
4825 			if (fShelf) {
4826 				message->PopSpecifier();
4827 				return fShelf;
4828 			}
4829 
4830 			err = B_NAME_NOT_FOUND;
4831 			replyMsg.AddString("message", "This window doesn't have a shelf");
4832 			break;
4833 
4834 		case 4:
4835 		{
4836 			if (!fFirstChild) {
4837 				err = B_NAME_NOT_FOUND;
4838 				replyMsg.AddString("message", "This window doesn't have "
4839 					"children.");
4840 				break;
4841 			}
4842 			BView* child = NULL;
4843 			switch (what) {
4844 				case B_INDEX_SPECIFIER:
4845 				{
4846 					int32 index;
4847 					err = specifier->FindInt32("index", &index);
4848 					if (err == B_OK)
4849 						child = ChildAt(index);
4850 					break;
4851 				}
4852 				case B_REVERSE_INDEX_SPECIFIER:
4853 				{
4854 					int32 rindex;
4855 					err = specifier->FindInt32("index", &rindex);
4856 					if (err == B_OK)
4857 						child = ChildAt(CountChildren() - rindex);
4858 					break;
4859 				}
4860 				case B_NAME_SPECIFIER:
4861 				{
4862 					const char* name;
4863 					err = specifier->FindString("name", &name);
4864 					if (err == B_OK)
4865 						child = FindView(name);
4866 					break;
4867 				}
4868 			}
4869 
4870 			if (child != NULL) {
4871 				message->PopSpecifier();
4872 				return child;
4873 			}
4874 
4875 			if (err == B_OK)
4876 				err = B_BAD_INDEX;
4877 
4878 			replyMsg.AddString("message",
4879 				"Cannot find view at/with specified index/name.");
4880 			break;
4881 		}
4882 
4883 		default:
4884 			return BHandler::ResolveSpecifier(message, index, specifier, what,
4885 				property);
4886 	}
4887 
4888 	if (err < B_OK) {
4889 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
4890 
4891 		if (err == B_BAD_SCRIPT_SYNTAX)
4892 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
4893 		else
4894 			replyMsg.AddString("message", strerror(err));
4895 	}
4896 
4897 	replyMsg.AddInt32("error", err);
4898 	message->SendReply(&replyMsg);
4899 	return NULL;
4900 }
4901 
4902 
4903 void
4904 BView::MessageReceived(BMessage* message)
4905 {
4906 	if (!message->HasSpecifiers()) {
4907 		switch (message->what) {
4908 			case B_VIEW_RESIZED:
4909 				FrameResized(message->GetInt32("width", 0),
4910 					message->GetInt32("height", 0));
4911 				break;
4912 
4913 			case B_VIEW_MOVED:
4914 				FrameMoved(fParentOffset);
4915 				break;
4916 
4917 			case B_MOUSE_IDLE:
4918 			{
4919 				BPoint where;
4920 				if (message->FindPoint("be:view_where", &where) != B_OK)
4921 					break;
4922 
4923 				BToolTip* tip;
4924 				if (GetToolTipAt(where, &tip))
4925 					ShowToolTip(tip);
4926 				else
4927 					BHandler::MessageReceived(message);
4928 				break;
4929 			}
4930 
4931 			case B_MOUSE_WHEEL_CHANGED:
4932 			{
4933 				BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
4934 				BScrollBar* vertical = ScrollBar(B_VERTICAL);
4935 				if (horizontal == NULL && vertical == NULL) {
4936 					// Pass the message to the next handler
4937 					BHandler::MessageReceived(message);
4938 					break;
4939 				}
4940 
4941 				float deltaX = 0.0f;
4942 				float deltaY = 0.0f;
4943 
4944 				if (horizontal != NULL)
4945 					message->FindFloat("be:wheel_delta_x", &deltaX);
4946 
4947 				if (vertical != NULL)
4948 					message->FindFloat("be:wheel_delta_y", &deltaY);
4949 
4950 				if (deltaX == 0.0f && deltaY == 0.0f)
4951 					break;
4952 
4953 				if ((modifiers() & B_CONTROL_KEY) != 0)
4954 					std::swap(horizontal, vertical);
4955 
4956 				if (horizontal != NULL && deltaX != 0.0f)
4957 					ScrollWithMouseWheelDelta(horizontal, deltaX);
4958 
4959 				if (vertical != NULL && deltaY != 0.0f)
4960 					ScrollWithMouseWheelDelta(vertical, deltaY);
4961 
4962 				break;
4963 			}
4964 
4965 			// prevent message repeats
4966 			case B_COLORS_UPDATED:
4967 			case B_FONTS_UPDATED:
4968 				break;
4969 
4970 			case B_SCREEN_CHANGED:
4971 			{
4972 				// propegate message to child views
4973 				int32 childCount = CountChildren();
4974 				for (int32 i = 0; i < childCount; i++) {
4975 					BView* view = ChildAt(i);
4976 					if (view != NULL)
4977 						view->MessageReceived(message);
4978 				}
4979 				break;
4980 			}
4981 
4982 			default:
4983 				BHandler::MessageReceived(message);
4984 				break;
4985 		}
4986 
4987 		return;
4988 	}
4989 
4990 	// Scripting message
4991 
4992 	BMessage replyMsg(B_REPLY);
4993 	status_t err = B_BAD_SCRIPT_SYNTAX;
4994 	int32 index;
4995 	BMessage specifier;
4996 	int32 what;
4997 	const char* property;
4998 
4999 	if (message->GetCurrentSpecifier(&index, &specifier, &what, &property)
5000 			!= B_OK) {
5001 		return BHandler::MessageReceived(message);
5002 	}
5003 
5004 	BPropertyInfo propertyInfo(sViewPropInfo);
5005 	switch (propertyInfo.FindMatch(message, index, &specifier, what,
5006 			property)) {
5007 		case 0:
5008 			if (message->what == B_GET_PROPERTY) {
5009 				err = replyMsg.AddRect("result", Frame());
5010 			} else if (message->what == B_SET_PROPERTY) {
5011 				BRect newFrame;
5012 				err = message->FindRect("data", &newFrame);
5013 				if (err == B_OK) {
5014 					MoveTo(newFrame.LeftTop());
5015 					ResizeTo(newFrame.Width(), newFrame.Height());
5016 				}
5017 			}
5018 			break;
5019 		case 1:
5020 			if (message->what == B_GET_PROPERTY) {
5021 				err = replyMsg.AddBool("result", IsHidden());
5022 			} else if (message->what == B_SET_PROPERTY) {
5023 				bool newHiddenState;
5024 				err = message->FindBool("data", &newHiddenState);
5025 				if (err == B_OK) {
5026 					if (newHiddenState == true)
5027 						Hide();
5028 					else
5029 						Show();
5030 				}
5031 			}
5032 			break;
5033 		case 3:
5034 			err = replyMsg.AddInt32("result", CountChildren());
5035 			break;
5036 		default:
5037 			return BHandler::MessageReceived(message);
5038 	}
5039 
5040 	if (err != B_OK) {
5041 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
5042 
5043 		if (err == B_BAD_SCRIPT_SYNTAX)
5044 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
5045 		else
5046 			replyMsg.AddString("message", strerror(err));
5047 
5048 		replyMsg.AddInt32("error", err);
5049 	}
5050 
5051 	message->SendReply(&replyMsg);
5052 }
5053 
5054 
5055 status_t
5056 BView::Perform(perform_code code, void* _data)
5057 {
5058 	switch (code) {
5059 		case PERFORM_CODE_MIN_SIZE:
5060 			((perform_data_min_size*)_data)->return_value
5061 				= BView::MinSize();
5062 			return B_OK;
5063 		case PERFORM_CODE_MAX_SIZE:
5064 			((perform_data_max_size*)_data)->return_value
5065 				= BView::MaxSize();
5066 			return B_OK;
5067 		case PERFORM_CODE_PREFERRED_SIZE:
5068 			((perform_data_preferred_size*)_data)->return_value
5069 				= BView::PreferredSize();
5070 			return B_OK;
5071 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
5072 			((perform_data_layout_alignment*)_data)->return_value
5073 				= BView::LayoutAlignment();
5074 			return B_OK;
5075 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
5076 			((perform_data_has_height_for_width*)_data)->return_value
5077 				= BView::HasHeightForWidth();
5078 			return B_OK;
5079 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
5080 		{
5081 			perform_data_get_height_for_width* data
5082 				= (perform_data_get_height_for_width*)_data;
5083 			BView::GetHeightForWidth(data->width, &data->min, &data->max,
5084 				&data->preferred);
5085 			return B_OK;
5086 		}
5087 		case PERFORM_CODE_SET_LAYOUT:
5088 		{
5089 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
5090 			BView::SetLayout(data->layout);
5091 			return B_OK;
5092 		}
5093 		case PERFORM_CODE_LAYOUT_INVALIDATED:
5094 		{
5095 			perform_data_layout_invalidated* data
5096 				= (perform_data_layout_invalidated*)_data;
5097 			BView::LayoutInvalidated(data->descendants);
5098 			return B_OK;
5099 		}
5100 		case PERFORM_CODE_DO_LAYOUT:
5101 		{
5102 			BView::DoLayout();
5103 			return B_OK;
5104 		}
5105 		case PERFORM_CODE_LAYOUT_CHANGED:
5106 		{
5107 			BView::LayoutChanged();
5108 			return B_OK;
5109 		}
5110 		case PERFORM_CODE_GET_TOOL_TIP_AT:
5111 		{
5112 			perform_data_get_tool_tip_at* data
5113 				= (perform_data_get_tool_tip_at*)_data;
5114 			data->return_value
5115 				= BView::GetToolTipAt(data->point, data->tool_tip);
5116 			return B_OK;
5117 		}
5118 		case PERFORM_CODE_ALL_UNARCHIVED:
5119 		{
5120 			perform_data_all_unarchived* data =
5121 				(perform_data_all_unarchived*)_data;
5122 
5123 			data->return_value = BView::AllUnarchived(data->archive);
5124 			return B_OK;
5125 		}
5126 		case PERFORM_CODE_ALL_ARCHIVED:
5127 		{
5128 			perform_data_all_archived* data =
5129 				(perform_data_all_archived*)_data;
5130 
5131 			data->return_value = BView::AllArchived(data->archive);
5132 			return B_OK;
5133 		}
5134 	}
5135 
5136 	return BHandler::Perform(code, _data);
5137 }
5138 
5139 
5140 // #pragma mark - Layout Functions
5141 
5142 
5143 BSize
5144 BView::MinSize()
5145 {
5146 	// TODO: make sure this works correctly when some methods are overridden
5147 	float width, height;
5148 	GetPreferredSize(&width, &height);
5149 
5150 	return BLayoutUtils::ComposeSize(fLayoutData->fMinSize,
5151 		(fLayoutData->fLayout ? fLayoutData->fLayout->MinSize()
5152 			: BSize(width, height)));
5153 }
5154 
5155 
5156 BSize
5157 BView::MaxSize()
5158 {
5159 	return BLayoutUtils::ComposeSize(fLayoutData->fMaxSize,
5160 		(fLayoutData->fLayout ? fLayoutData->fLayout->MaxSize()
5161 			: BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)));
5162 }
5163 
5164 
5165 BSize
5166 BView::PreferredSize()
5167 {
5168 	// TODO: make sure this works correctly when some methods are overridden
5169 	float width, height;
5170 	GetPreferredSize(&width, &height);
5171 
5172 	return BLayoutUtils::ComposeSize(fLayoutData->fPreferredSize,
5173 		(fLayoutData->fLayout ? fLayoutData->fLayout->PreferredSize()
5174 			: BSize(width, height)));
5175 }
5176 
5177 
5178 BAlignment
5179 BView::LayoutAlignment()
5180 {
5181 	return BLayoutUtils::ComposeAlignment(fLayoutData->fAlignment,
5182 		(fLayoutData->fLayout ? fLayoutData->fLayout->Alignment()
5183 			: BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER)));
5184 }
5185 
5186 
5187 void
5188 BView::SetExplicitMinSize(BSize size)
5189 {
5190 	fLayoutData->fMinSize = size;
5191 	InvalidateLayout();
5192 }
5193 
5194 
5195 void
5196 BView::SetExplicitMaxSize(BSize size)
5197 {
5198 	fLayoutData->fMaxSize = size;
5199 	InvalidateLayout();
5200 }
5201 
5202 
5203 void
5204 BView::SetExplicitPreferredSize(BSize size)
5205 {
5206 	fLayoutData->fPreferredSize = size;
5207 	InvalidateLayout();
5208 }
5209 
5210 
5211 void
5212 BView::SetExplicitSize(BSize size)
5213 {
5214 	fLayoutData->fMinSize = size;
5215 	fLayoutData->fMaxSize = size;
5216 	fLayoutData->fPreferredSize = size;
5217 	InvalidateLayout();
5218 }
5219 
5220 
5221 void
5222 BView::SetExplicitAlignment(BAlignment alignment)
5223 {
5224 	fLayoutData->fAlignment = alignment;
5225 	InvalidateLayout();
5226 }
5227 
5228 
5229 BSize
5230 BView::ExplicitMinSize() const
5231 {
5232 	return fLayoutData->fMinSize;
5233 }
5234 
5235 
5236 BSize
5237 BView::ExplicitMaxSize() const
5238 {
5239 	return fLayoutData->fMaxSize;
5240 }
5241 
5242 
5243 BSize
5244 BView::ExplicitPreferredSize() const
5245 {
5246 	return fLayoutData->fPreferredSize;
5247 }
5248 
5249 
5250 BAlignment
5251 BView::ExplicitAlignment() const
5252 {
5253 	return fLayoutData->fAlignment;
5254 }
5255 
5256 
5257 bool
5258 BView::HasHeightForWidth()
5259 {
5260 	return (fLayoutData->fLayout
5261 		? fLayoutData->fLayout->HasHeightForWidth() : false);
5262 }
5263 
5264 
5265 void
5266 BView::GetHeightForWidth(float width, float* min, float* max, float* preferred)
5267 {
5268 	if (fLayoutData->fLayout)
5269 		fLayoutData->fLayout->GetHeightForWidth(width, min, max, preferred);
5270 }
5271 
5272 
5273 void
5274 BView::SetLayout(BLayout* layout)
5275 {
5276 	if (layout == fLayoutData->fLayout)
5277 		return;
5278 
5279 	if (layout && layout->Layout())
5280 		debugger("BView::SetLayout() failed, layout is already in use.");
5281 
5282 	fFlags |= B_SUPPORTS_LAYOUT;
5283 
5284 	// unset and delete the old layout
5285 	if (fLayoutData->fLayout) {
5286 		fLayoutData->fLayout->RemoveSelf();
5287 		fLayoutData->fLayout->SetOwner(NULL);
5288 		delete fLayoutData->fLayout;
5289 	}
5290 
5291 	fLayoutData->fLayout = layout;
5292 
5293 	if (fLayoutData->fLayout) {
5294 		fLayoutData->fLayout->SetOwner(this);
5295 
5296 		// add all children
5297 		int count = CountChildren();
5298 		for (int i = 0; i < count; i++)
5299 			fLayoutData->fLayout->AddView(ChildAt(i));
5300 	}
5301 
5302 	InvalidateLayout();
5303 }
5304 
5305 
5306 BLayout*
5307 BView::GetLayout() const
5308 {
5309 	return fLayoutData->fLayout;
5310 }
5311 
5312 
5313 void
5314 BView::InvalidateLayout(bool descendants)
5315 {
5316 	// printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
5317 	//	this, descendants, fLayoutData->fLayoutValid,
5318 	//	fLayoutData->fLayoutInProgress);
5319 
5320 	if (!fLayoutData->fMinMaxValid || fLayoutData->fLayoutInProgress
5321  			|| fLayoutData->fLayoutInvalidationDisabled > 0) {
5322 		return;
5323 	}
5324 	fLayoutData->fLayoutValid = false;
5325 	fLayoutData->fMinMaxValid = false;
5326 	LayoutInvalidated(descendants);
5327 
5328 	if (descendants) {
5329 		for (BView* child = fFirstChild;
5330 			child; child = child->fNextSibling) {
5331 			child->InvalidateLayout(descendants);
5332 		}
5333 	}
5334 
5335 	if (fLayoutData->fLayout)
5336 		fLayoutData->fLayout->InvalidateLayout(descendants);
5337 	else
5338 		_InvalidateParentLayout();
5339 
5340 	if (fTopLevelView
5341 		&& fOwner != NULL)
5342 		fOwner->PostMessage(B_LAYOUT_WINDOW);
5343 }
5344 
5345 
5346 void
5347 BView::EnableLayoutInvalidation()
5348 {
5349 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5350 		fLayoutData->fLayoutInvalidationDisabled--;
5351 }
5352 
5353 
5354 void
5355 BView::DisableLayoutInvalidation()
5356 {
5357 	fLayoutData->fLayoutInvalidationDisabled++;
5358 }
5359 
5360 
5361 bool
5362 BView::IsLayoutInvalidationDisabled()
5363 {
5364 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5365 		return true;
5366 	return false;
5367 }
5368 
5369 
5370 bool
5371 BView::IsLayoutValid() const
5372 {
5373 	return fLayoutData->fLayoutValid;
5374 }
5375 
5376 
5377 void
5378 BView::ResetLayoutInvalidation()
5379 {
5380 	fLayoutData->fMinMaxValid = true;
5381 }
5382 
5383 
5384 BLayoutContext*
5385 BView::LayoutContext() const
5386 {
5387 	return fLayoutData->fLayoutContext;
5388 }
5389 
5390 
5391 void
5392 BView::Layout(bool force)
5393 {
5394 	BLayoutContext context;
5395 	_Layout(force, &context);
5396 }
5397 
5398 
5399 void
5400 BView::Relayout()
5401 {
5402 	if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) {
5403 		fLayoutData->fNeedsRelayout = true;
5404 		if (fLayoutData->fLayout)
5405 			fLayoutData->fLayout->RequireLayout();
5406 
5407 		// Layout() is recursive, that is if the parent view is currently laid
5408 		// out, we don't call layout() on this view, but wait for the parent's
5409 		// Layout() to do that for us.
5410 		if (!fParent || !fParent->fLayoutData->fLayoutInProgress)
5411 			Layout(false);
5412 	}
5413 }
5414 
5415 
5416 void
5417 BView::LayoutInvalidated(bool descendants)
5418 {
5419 	// hook method
5420 }
5421 
5422 
5423 void
5424 BView::DoLayout()
5425 {
5426 	if (fLayoutData->fLayout)
5427 		fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
5428 }
5429 
5430 
5431 void
5432 BView::SetToolTip(const char* text)
5433 {
5434 	if (text == NULL || text[0] == '\0') {
5435 		SetToolTip((BToolTip*)NULL);
5436 		return;
5437 	}
5438 
5439 	if (BTextToolTip* tip = dynamic_cast<BTextToolTip*>(fToolTip))
5440 		tip->SetText(text);
5441 	else
5442 		SetToolTip(new BTextToolTip(text));
5443 }
5444 
5445 
5446 void
5447 BView::SetToolTip(BToolTip* tip)
5448 {
5449 	if (fToolTip == tip)
5450 		return;
5451 	else if (tip == NULL)
5452 		HideToolTip();
5453 
5454 	if (fToolTip != NULL)
5455 		fToolTip->ReleaseReference();
5456 
5457 	fToolTip = tip;
5458 
5459 	if (fToolTip != NULL)
5460 		fToolTip->AcquireReference();
5461 }
5462 
5463 
5464 BToolTip*
5465 BView::ToolTip() const
5466 {
5467 	return fToolTip;
5468 }
5469 
5470 
5471 void
5472 BView::ShowToolTip(BToolTip* tip)
5473 {
5474 	if (tip == NULL)
5475 		return;
5476 
5477 	BPoint where;
5478 	GetMouse(&where, NULL, false);
5479 
5480 	BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where), this);
5481 }
5482 
5483 
5484 void
5485 BView::HideToolTip()
5486 {
5487 	BToolTipManager::Manager()->HideTip();
5488 }
5489 
5490 
5491 bool
5492 BView::GetToolTipAt(BPoint point, BToolTip** _tip)
5493 {
5494 	if (fToolTip != NULL) {
5495 		*_tip = fToolTip;
5496 		return true;
5497 	}
5498 
5499 	*_tip = NULL;
5500 	return false;
5501 }
5502 
5503 
5504 void
5505 BView::LayoutChanged()
5506 {
5507 	// hook method
5508 }
5509 
5510 
5511 void
5512 BView::_Layout(bool force, BLayoutContext* context)
5513 {
5514 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context);
5515 //printf("  fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n",
5516 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid,
5517 //fLayoutData->fLayoutInProgress);
5518 	if (fLayoutData->fNeedsRelayout || !fLayoutData->fLayoutValid || force) {
5519 		fLayoutData->fLayoutValid = false;
5520 
5521 		if (fLayoutData->fLayoutInProgress)
5522 			return;
5523 
5524 		BLayoutContext* oldContext = fLayoutData->fLayoutContext;
5525 		fLayoutData->fLayoutContext = context;
5526 
5527 		fLayoutData->fLayoutInProgress = true;
5528 		DoLayout();
5529 		fLayoutData->fLayoutInProgress = false;
5530 
5531 		fLayoutData->fLayoutValid = true;
5532 		fLayoutData->fMinMaxValid = true;
5533 		fLayoutData->fNeedsRelayout = false;
5534 
5535 		// layout children
5536 		for(BView* child = fFirstChild; child; child = child->fNextSibling) {
5537 			if (!child->IsHidden(child))
5538 				child->_Layout(force, context);
5539 		}
5540 
5541 		LayoutChanged();
5542 
5543 		fLayoutData->fLayoutContext = oldContext;
5544 
5545 		// invalidate the drawn content, if requested
5546 		if (fFlags & B_INVALIDATE_AFTER_LAYOUT)
5547 			Invalidate();
5548 	}
5549 }
5550 
5551 
5552 void
5553 BView::_LayoutLeft(BLayout* deleted)
5554 {
5555 	// If our layout is added to another layout (via BLayout::AddItem())
5556 	// then we share ownership of our layout. In the event that our layout gets
5557 	// deleted by the layout it has been added to, this method is called so
5558 	// that we don't double-delete our layout.
5559 	if (fLayoutData->fLayout == deleted)
5560 		fLayoutData->fLayout = NULL;
5561 	InvalidateLayout();
5562 }
5563 
5564 
5565 void
5566 BView::_InvalidateParentLayout()
5567 {
5568 	if (!fParent)
5569 		return;
5570 
5571 	BLayout* layout = fLayoutData->fLayout;
5572 	BLayout* layoutParent = layout ? layout->Layout() : NULL;
5573 	if (layoutParent) {
5574 		layoutParent->InvalidateLayout();
5575 	} else if (fLayoutData->fLayoutItems.CountItems() > 0) {
5576 		int32 count = fLayoutData->fLayoutItems.CountItems();
5577 		for (int32 i = 0; i < count; i++) {
5578 			fLayoutData->fLayoutItems.ItemAt(i)->Layout()->InvalidateLayout();
5579 		}
5580 	} else {
5581 		fParent->InvalidateLayout();
5582 	}
5583 }
5584 
5585 
5586 //	#pragma mark - Private Functions
5587 
5588 
5589 void
5590 BView::_InitData(BRect frame, const char* name, uint32 resizingMode,
5591 	uint32 flags)
5592 {
5593 	// Info: The name of the view is set by BHandler constructor
5594 
5595 	STRACE(("BView::_InitData: enter\n"));
5596 
5597 	// initialize members
5598 	if ((resizingMode & ~_RESIZE_MASK_) || (flags & _RESIZE_MASK_))
5599 		printf("%s BView::_InitData(): resizing mode or flags swapped\n", name);
5600 
5601 	// There are applications that swap the resize mask and the flags in the
5602 	// BView constructor. This does not cause problems under BeOS as it just
5603 	// ors the two fields to one 32bit flag.
5604 	// For now we do the same but print the above warning message.
5605 	// TODO: this should be removed at some point and the original
5606 	// version restored:
5607 	// fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
5608 	fFlags = resizingMode | flags;
5609 
5610 	// handle rounding
5611 	frame.left = roundf(frame.left);
5612 	frame.top = roundf(frame.top);
5613 	frame.right = roundf(frame.right);
5614 	frame.bottom = roundf(frame.bottom);
5615 
5616 	fParentOffset.Set(frame.left, frame.top);
5617 
5618 	fOwner = NULL;
5619 	fParent = NULL;
5620 	fNextSibling = NULL;
5621 	fPreviousSibling = NULL;
5622 	fFirstChild = NULL;
5623 
5624 	fShowLevel = 0;
5625 	fTopLevelView = false;
5626 
5627 	fCurrentPicture = NULL;
5628 	fCommArray = NULL;
5629 
5630 	fVerScroller = NULL;
5631 	fHorScroller = NULL;
5632 
5633 	fIsPrinting = false;
5634 	fAttached = false;
5635 
5636 	// TODO: Since we cannot communicate failure, we don't use std::nothrow here
5637 	// TODO: Maybe we could auto-delete those views on AddChild() instead?
5638 	fState = new BPrivate::ViewState;
5639 
5640 	fBounds = frame.OffsetToCopy(B_ORIGIN);
5641 	fShelf = NULL;
5642 
5643 	fEventMask = 0;
5644 	fEventOptions = 0;
5645 	fMouseEventOptions = 0;
5646 
5647 	fLayoutData = new LayoutData;
5648 
5649 	fToolTip = NULL;
5650 
5651 	if ((flags & B_SUPPORTS_LAYOUT) != 0) {
5652 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
5653 		SetLowUIColor(ViewUIColor());
5654 		SetHighUIColor(B_PANEL_TEXT_COLOR);
5655 	}
5656 }
5657 
5658 
5659 void
5660 BView::_RemoveCommArray()
5661 {
5662 	if (fCommArray) {
5663 		delete [] fCommArray->array;
5664 		delete fCommArray;
5665 		fCommArray = NULL;
5666 	}
5667 }
5668 
5669 
5670 void
5671 BView::_SetOwner(BWindow* newOwner)
5672 {
5673 	if (!newOwner)
5674 		_RemoveCommArray();
5675 
5676 	if (fOwner != newOwner && fOwner) {
5677 		if (fOwner->fFocus == this)
5678 			MakeFocus(false);
5679 
5680 		if (fOwner->fLastMouseMovedView == this)
5681 			fOwner->fLastMouseMovedView = NULL;
5682 
5683 		fOwner->RemoveHandler(this);
5684 		if (fShelf)
5685 			fOwner->RemoveHandler(fShelf);
5686 	}
5687 
5688 	if (newOwner && newOwner != fOwner) {
5689 		newOwner->AddHandler(this);
5690 		if (fShelf)
5691 			newOwner->AddHandler(fShelf);
5692 
5693 		if (fTopLevelView)
5694 			SetNextHandler(newOwner);
5695 		else
5696 			SetNextHandler(fParent);
5697 	}
5698 
5699 	fOwner = newOwner;
5700 
5701 	for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling)
5702 		child->_SetOwner(newOwner);
5703 }
5704 
5705 
5706 void
5707 BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
5708 {
5709 	if (!_CheckOwnerLockAndSwitchCurrent())
5710 		return;
5711 
5712 	if (picture == NULL) {
5713 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5714 		fOwner->fLink->Attach<int32>(-1);
5715 
5716 		// NOTE: No need to sync here, since the -1 token cannot
5717 		// become invalid on the server.
5718 	} else {
5719 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5720 		fOwner->fLink->Attach<int32>(picture->Token());
5721 		fOwner->fLink->Attach<BPoint>(where);
5722 		fOwner->fLink->Attach<bool>(invert);
5723 
5724 		// NOTE: "sync" defaults to true in public methods. If you know what
5725 		// you are doing, i.e. if you know your BPicture stays valid, you
5726 		// can avoid the performance impact of syncing. In a use-case where
5727 		// the client creates BPictures on the stack, these BPictures may
5728 		// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
5729 		// goes out of scope, and the command is processed earlier in the
5730 		// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
5731 		// ServerWindow thread, which will then have the result that no
5732 		// ServerPicture is found of the token.
5733 		if (sync)
5734 			Sync();
5735 	}
5736 }
5737 
5738 
5739 void
5740 BView::_ClipToRect(BRect rect, bool inverse)
5741 {
5742 	if (_CheckOwnerLockAndSwitchCurrent()) {
5743 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_RECT);
5744 		fOwner->fLink->Attach<bool>(inverse);
5745 		fOwner->fLink->Attach<BRect>(rect);
5746 		_FlushIfNotInTransaction();
5747 	}
5748 }
5749 
5750 
5751 void
5752 BView::_ClipToShape(BShape* shape, bool inverse)
5753 {
5754 	if (shape == NULL)
5755 		return;
5756 
5757 	shape_data* sd = (shape_data*)shape->fPrivateData;
5758 	if (sd->opCount == 0 || sd->ptCount == 0)
5759 		return;
5760 
5761 	if (_CheckOwnerLockAndSwitchCurrent()) {
5762 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_SHAPE);
5763 		fOwner->fLink->Attach<bool>(inverse);
5764 		fOwner->fLink->Attach<int32>(sd->opCount);
5765 		fOwner->fLink->Attach<int32>(sd->ptCount);
5766 		fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32));
5767 		fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
5768 		_FlushIfNotInTransaction();
5769 	}
5770 }
5771 
5772 
5773 bool
5774 BView::_RemoveChildFromList(BView* child)
5775 {
5776 	if (child->fParent != this)
5777 		return false;
5778 
5779 	if (fFirstChild == child) {
5780 		// it's the first view in the list
5781 		fFirstChild = child->fNextSibling;
5782 	} else {
5783 		// there must be a previous sibling
5784 		child->fPreviousSibling->fNextSibling = child->fNextSibling;
5785 	}
5786 
5787 	if (child->fNextSibling)
5788 		child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
5789 
5790 	child->fParent = NULL;
5791 	child->fNextSibling = NULL;
5792 	child->fPreviousSibling = NULL;
5793 
5794 	return true;
5795 }
5796 
5797 
5798 bool
5799 BView::_AddChildToList(BView* child, BView* before)
5800 {
5801 	if (!child)
5802 		return false;
5803 	if (child->fParent != NULL) {
5804 		debugger("View already belongs to someone else");
5805 		return false;
5806 	}
5807 	if (before != NULL && before->fParent != this) {
5808 		debugger("Invalid before view");
5809 		return false;
5810 	}
5811 
5812 	if (before != NULL) {
5813 		// add view before this one
5814 		child->fNextSibling = before;
5815 		child->fPreviousSibling = before->fPreviousSibling;
5816 		if (child->fPreviousSibling != NULL)
5817 			child->fPreviousSibling->fNextSibling = child;
5818 
5819 		before->fPreviousSibling = child;
5820 		if (fFirstChild == before)
5821 			fFirstChild = child;
5822 	} else {
5823 		// add view to the end of the list
5824 		BView* last = fFirstChild;
5825 		while (last != NULL && last->fNextSibling != NULL) {
5826 			last = last->fNextSibling;
5827 		}
5828 
5829 		if (last != NULL) {
5830 			last->fNextSibling = child;
5831 			child->fPreviousSibling = last;
5832 		} else {
5833 			fFirstChild = child;
5834 			child->fPreviousSibling = NULL;
5835 		}
5836 
5837 		child->fNextSibling = NULL;
5838 	}
5839 
5840 	child->fParent = this;
5841 	return true;
5842 }
5843 
5844 
5845 /*!	\brief Creates the server counterpart of this view.
5846 	This is only done for views that are part of the view hierarchy, ie. when
5847 	they are attached to a window.
5848 	RemoveSelf() deletes the server object again.
5849 */
5850 bool
5851 BView::_CreateSelf()
5852 {
5853 	// AS_VIEW_CREATE & AS_VIEW_CREATE_ROOT do not use the
5854 	// current view mechanism via _CheckLockAndSwitchCurrent() - the token
5855 	// of the view and its parent are both send to the server.
5856 
5857 	if (fTopLevelView)
5858 		fOwner->fLink->StartMessage(AS_VIEW_CREATE_ROOT);
5859 	else
5860  		fOwner->fLink->StartMessage(AS_VIEW_CREATE);
5861 
5862 	fOwner->fLink->Attach<int32>(_get_object_token_(this));
5863 	fOwner->fLink->AttachString(Name());
5864 	fOwner->fLink->Attach<BRect>(Frame());
5865 	fOwner->fLink->Attach<BPoint>(LeftTop());
5866 	fOwner->fLink->Attach<uint32>(ResizingMode());
5867 	fOwner->fLink->Attach<uint32>(fEventMask);
5868 	fOwner->fLink->Attach<uint32>(fEventOptions);
5869 	fOwner->fLink->Attach<uint32>(Flags());
5870 	fOwner->fLink->Attach<bool>(IsHidden(this));
5871 	fOwner->fLink->Attach<rgb_color>(fState->view_color);
5872 	if (fTopLevelView)
5873 		fOwner->fLink->Attach<int32>(B_NULL_TOKEN);
5874 	else
5875 		fOwner->fLink->Attach<int32>(_get_object_token_(fParent));
5876 	fOwner->fLink->Flush();
5877 
5878 	_CheckOwnerLockAndSwitchCurrent();
5879 	fState->UpdateServerState(*fOwner->fLink);
5880 
5881 	// we create all its children, too
5882 
5883 	for (BView* child = fFirstChild; child != NULL;
5884 			child = child->fNextSibling) {
5885 		child->_CreateSelf();
5886 	}
5887 
5888 	fOwner->fLink->Flush();
5889 	return true;
5890 }
5891 
5892 
5893 /*!	Sets the new view position.
5894 	It doesn't contact the server, though - the only case where this
5895 	is called outside of MoveTo() is as reaction of moving a view
5896 	in the server (a.k.a. B_WINDOW_RESIZED).
5897 	It also calls the BView's FrameMoved() hook.
5898 */
5899 void
5900 BView::_MoveTo(int32 x, int32 y)
5901 {
5902 	fParentOffset.Set(x, y);
5903 
5904 	if (Window() != NULL && fFlags & B_FRAME_EVENTS) {
5905 		BMessage moved(B_VIEW_MOVED);
5906 		moved.AddInt64("when", system_time());
5907 		moved.AddPoint("where", BPoint(x, y));
5908 
5909 		BMessenger target(this);
5910 		target.SendMessage(&moved);
5911 	}
5912 }
5913 
5914 
5915 /*!	Computes the actual new frame size and recalculates the size of
5916 	the children as well.
5917 	It doesn't contact the server, though - the only case where this
5918 	is called outside of ResizeBy() is as reaction of resizing a view
5919 	in the server (a.k.a. B_WINDOW_RESIZED).
5920 	It also calls the BView's FrameResized() hook.
5921 */
5922 void
5923 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight)
5924 {
5925 	fBounds.right += deltaWidth;
5926 	fBounds.bottom += deltaHeight;
5927 
5928 	if (Window() == NULL) {
5929 		// we're not supposed to exercise the resizing code in case
5930 		// we haven't been attached to a window yet
5931 		return;
5932 	}
5933 
5934 	// layout the children
5935 	if ((fFlags & B_SUPPORTS_LAYOUT) != 0) {
5936 		Relayout();
5937 	} else {
5938 		for (BView* child = fFirstChild; child; child = child->fNextSibling)
5939 			child->_ParentResizedBy(deltaWidth, deltaHeight);
5940 	}
5941 
5942 	if (fFlags & B_FRAME_EVENTS) {
5943 		BMessage resized(B_VIEW_RESIZED);
5944 		resized.AddInt64("when", system_time());
5945 		resized.AddInt32("width", fBounds.IntegerWidth());
5946 		resized.AddInt32("height", fBounds.IntegerHeight());
5947 
5948 		BMessenger target(this);
5949 		target.SendMessage(&resized);
5950 	}
5951 }
5952 
5953 
5954 /*!	Relayouts the view according to its resizing mode. */
5955 void
5956 BView::_ParentResizedBy(int32 x, int32 y)
5957 {
5958 	uint32 resizingMode = fFlags & _RESIZE_MASK_;
5959 	BRect newFrame = Frame();
5960 
5961 	// follow with left side
5962 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
5963 		newFrame.left += x;
5964 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
5965 		newFrame.left += x / 2;
5966 
5967 	// follow with right side
5968 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
5969 		newFrame.right += x;
5970 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
5971 		newFrame.right += x / 2;
5972 
5973 	// follow with top side
5974 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
5975 		newFrame.top += y;
5976 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
5977 		newFrame.top += y / 2;
5978 
5979 	// follow with bottom side
5980 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
5981 		newFrame.bottom += y;
5982 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
5983 		newFrame.bottom += y / 2;
5984 
5985 	if (newFrame.LeftTop() != fParentOffset) {
5986 		// move view
5987 		_MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top));
5988 	}
5989 
5990 	if (newFrame != Frame()) {
5991 		// resize view
5992 		int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width());
5993 		int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height());
5994 		_ResizeBy(widthDiff, heightDiff);
5995 	}
5996 }
5997 
5998 
5999 void
6000 BView::_Activate(bool active)
6001 {
6002 	WindowActivated(active);
6003 
6004 	for (BView* child = fFirstChild; child != NULL;
6005 			child = child->fNextSibling) {
6006 		child->_Activate(active);
6007 	}
6008 }
6009 
6010 
6011 void
6012 BView::_Attach()
6013 {
6014 	if (fOwner != NULL) {
6015 		// unmask state flags to force [re]syncing with the app_server
6016 		fState->valid_flags &= ~(B_VIEW_WHICH_VIEW_COLOR_BIT
6017 			| B_VIEW_WHICH_LOW_COLOR_BIT | B_VIEW_WHICH_HIGH_COLOR_BIT);
6018 
6019 		if (fState->which_view_color != B_NO_COLOR)
6020 			SetViewUIColor(fState->which_view_color,
6021 				fState->which_view_color_tint);
6022 
6023 		if (fState->which_high_color != B_NO_COLOR)
6024 			SetHighUIColor(fState->which_high_color,
6025 				fState->which_high_color_tint);
6026 
6027 		if (fState->which_low_color != B_NO_COLOR)
6028 			SetLowUIColor(fState->which_low_color,
6029 				fState->which_low_color_tint);
6030 	}
6031 
6032 	AttachedToWindow();
6033 
6034 	fAttached = true;
6035 
6036 	// after giving the view a chance to do this itself,
6037 	// check for the B_PULSE_NEEDED flag and make sure the
6038 	// window set's up the pulse messaging
6039 	if (fOwner) {
6040 		if (fFlags & B_PULSE_NEEDED) {
6041 			_CheckLock();
6042 			if (fOwner->fPulseRunner == NULL)
6043 				fOwner->SetPulseRate(fOwner->PulseRate());
6044 		}
6045 
6046 		if (!fOwner->IsHidden())
6047 			Invalidate();
6048 	}
6049 
6050 	for (BView* child = fFirstChild; child != NULL;
6051 			child = child->fNextSibling) {
6052 		// we need to check for fAttached as new views could have been
6053 		// added in AttachedToWindow() - and those are already attached
6054 		if (!child->fAttached)
6055 			child->_Attach();
6056 	}
6057 
6058 	AllAttached();
6059 }
6060 
6061 
6062 void
6063 BView::_ColorsUpdated(BMessage* message)
6064 {
6065 	if (fTopLevelView
6066 		&& fLayoutData->fLayout != NULL
6067 		&& !fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)) {
6068 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
6069 		SetHighUIColor(B_PANEL_TEXT_COLOR);
6070 	}
6071 
6072 	rgb_color color;
6073 
6074 	const char* colorName = ui_color_name(fState->which_view_color);
6075 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6076 		fState->view_color = tint_color(color, fState->which_view_color_tint);
6077 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
6078 	}
6079 
6080 	colorName = ui_color_name(fState->which_low_color);
6081 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6082 		fState->low_color = tint_color(color, fState->which_low_color_tint);
6083 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
6084 	}
6085 
6086 	colorName = ui_color_name(fState->which_high_color);
6087 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6088 		fState->high_color = tint_color(color, fState->which_high_color_tint);
6089 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
6090 	}
6091 
6092 	MessageReceived(message);
6093 
6094 	for (BView* child = fFirstChild; child != NULL;
6095 			child = child->fNextSibling)
6096 		child->_ColorsUpdated(message);
6097 
6098 	Invalidate();
6099 }
6100 
6101 
6102 void
6103 BView::_Detach()
6104 {
6105 	DetachedFromWindow();
6106 	fAttached = false;
6107 
6108 	for (BView* child = fFirstChild; child != NULL;
6109 			child = child->fNextSibling) {
6110 		child->_Detach();
6111 	}
6112 
6113 	AllDetached();
6114 
6115 	if (fOwner) {
6116 		_CheckLock();
6117 
6118 		if (!fOwner->IsHidden())
6119 			Invalidate();
6120 
6121 		// make sure our owner doesn't need us anymore
6122 
6123 		if (fOwner->CurrentFocus() == this) {
6124 			MakeFocus(false);
6125 			// MakeFocus() is virtual and might not be
6126 			// passing through to the BView version,
6127 			// but we need to make sure at this point
6128 			// that we are not the focus view anymore.
6129 			if (fOwner->CurrentFocus() == this)
6130 				fOwner->_SetFocus(NULL, true);
6131 		}
6132 
6133 		if (fOwner->fDefaultButton == this)
6134 			fOwner->SetDefaultButton(NULL);
6135 
6136 		if (fOwner->fKeyMenuBar == this)
6137 			fOwner->fKeyMenuBar = NULL;
6138 
6139 		if (fOwner->fLastMouseMovedView == this)
6140 			fOwner->fLastMouseMovedView = NULL;
6141 
6142 		if (fOwner->fLastViewToken == _get_object_token_(this))
6143 			fOwner->fLastViewToken = B_NULL_TOKEN;
6144 
6145 		_SetOwner(NULL);
6146 	}
6147 }
6148 
6149 
6150 void
6151 BView::_Draw(BRect updateRect)
6152 {
6153 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW))
6154 		return;
6155 
6156 	// NOTE: if ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW
6157 	// -> View is simply not drawn at all
6158 
6159 	_SwitchServerCurrentView();
6160 
6161 	ConvertFromScreen(&updateRect);
6162 
6163 	// TODO: make states robust (the hook implementation could
6164 	// mess things up if it uses non-matching Push- and PopState(),
6165 	// we would not be guaranteed to still have the same state on
6166 	// the stack after having called Draw())
6167 	PushState();
6168 	Draw(updateRect);
6169 	PopState();
6170 	Flush();
6171 }
6172 
6173 
6174 void
6175 BView::_DrawAfterChildren(BRect updateRect)
6176 {
6177 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW)
6178 		|| !(Flags() & B_DRAW_ON_CHILDREN))
6179 		return;
6180 
6181 	_SwitchServerCurrentView();
6182 
6183 	ConvertFromScreen(&updateRect);
6184 
6185 	// TODO: make states robust (see above)
6186 	PushState();
6187 	DrawAfterChildren(updateRect);
6188 	PopState();
6189 	Flush();
6190 }
6191 
6192 
6193 void
6194 BView::_FontsUpdated(BMessage* message)
6195 {
6196 	MessageReceived(message);
6197 
6198 	for (BView* child = fFirstChild; child != NULL;
6199 			child = child->fNextSibling) {
6200 		child->_FontsUpdated(message);
6201 	}
6202 }
6203 
6204 
6205 void
6206 BView::_Pulse()
6207 {
6208 	if ((Flags() & B_PULSE_NEEDED) != 0)
6209 		Pulse();
6210 
6211 	for (BView* child = fFirstChild; child != NULL;
6212 			child = child->fNextSibling) {
6213 		child->_Pulse();
6214 	}
6215 }
6216 
6217 
6218 void
6219 BView::_UpdateStateForRemove()
6220 {
6221 	// TODO: _CheckLockAndSwitchCurrent() would be good enough, no?
6222 	if (!_CheckOwnerLockAndSwitchCurrent())
6223 		return;
6224 
6225 	fState->UpdateFrom(*fOwner->fLink);
6226 //	if (!fState->IsValid(B_VIEW_FRAME_BIT)) {
6227 //		fOwner->fLink->StartMessage(AS_VIEW_GET_COORD);
6228 //
6229 //		status_t code;
6230 //		if (fOwner->fLink->FlushWithReply(code) == B_OK
6231 //			&& code == B_OK) {
6232 //			fOwner->fLink->Read<BPoint>(&fParentOffset);
6233 //			fOwner->fLink->Read<BRect>(&fBounds);
6234 //			fState->valid_flags |= B_VIEW_FRAME_BIT;
6235 //		}
6236 //	}
6237 
6238 	// update children as well
6239 
6240 	for (BView* child = fFirstChild; child != NULL;
6241 			child = child->fNextSibling) {
6242 		if (child->fOwner)
6243 			child->_UpdateStateForRemove();
6244 	}
6245 }
6246 
6247 
6248 inline void
6249 BView::_UpdatePattern(::pattern pattern)
6250 {
6251 	if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern)
6252 		return;
6253 
6254 	if (fOwner) {
6255 		_CheckLockAndSwitchCurrent();
6256 
6257 		fOwner->fLink->StartMessage(AS_VIEW_SET_PATTERN);
6258 		fOwner->fLink->Attach< ::pattern>(pattern);
6259 
6260 		fState->valid_flags |= B_VIEW_PATTERN_BIT;
6261 	}
6262 
6263 	fState->pattern = pattern;
6264 }
6265 
6266 
6267 void
6268 BView::_FlushIfNotInTransaction()
6269 {
6270 	if (!fOwner->fInTransaction) {
6271 		fOwner->Flush();
6272 	}
6273 }
6274 
6275 
6276 BShelf*
6277 BView::_Shelf() const
6278 {
6279 	return fShelf;
6280 }
6281 
6282 
6283 void
6284 BView::_SetShelf(BShelf* shelf)
6285 {
6286 	if (fShelf != NULL && fOwner != NULL)
6287 		fOwner->RemoveHandler(fShelf);
6288 
6289 	fShelf = shelf;
6290 
6291 	if (fShelf != NULL && fOwner != NULL)
6292 		fOwner->AddHandler(fShelf);
6293 }
6294 
6295 
6296 status_t
6297 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
6298 	uint32 followFlags, uint32 options)
6299 {
6300 	if (!_CheckOwnerLockAndSwitchCurrent())
6301 		return B_ERROR;
6302 
6303 	int32 serverToken = bitmap ? bitmap->_ServerToken() : -1;
6304 
6305 	fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_BITMAP);
6306 	fOwner->fLink->Attach<int32>(serverToken);
6307 	fOwner->fLink->Attach<BRect>(srcRect);
6308 	fOwner->fLink->Attach<BRect>(dstRect);
6309 	fOwner->fLink->Attach<int32>(followFlags);
6310 	fOwner->fLink->Attach<int32>(options);
6311 
6312 	status_t status = B_ERROR;
6313 	fOwner->fLink->FlushWithReply(status);
6314 
6315 	return status;
6316 }
6317 
6318 
6319 bool
6320 BView::_CheckOwnerLockAndSwitchCurrent() const
6321 {
6322 	STRACE(("BView(%s)::_CheckOwnerLockAndSwitchCurrent()\n", Name()));
6323 
6324 	if (fOwner == NULL) {
6325 		debugger("View method requires owner and doesn't have one.");
6326 		return false;
6327 	}
6328 
6329 	_CheckLockAndSwitchCurrent();
6330 
6331 	return true;
6332 }
6333 
6334 
6335 bool
6336 BView::_CheckOwnerLock() const
6337 {
6338 	if (fOwner) {
6339 		fOwner->check_lock();
6340 		return true;
6341 	} else {
6342 		debugger("View method requires owner and doesn't have one.");
6343 		return false;
6344 	}
6345 }
6346 
6347 
6348 void
6349 BView::_CheckLockAndSwitchCurrent() const
6350 {
6351 	STRACE(("BView(%s)::_CheckLockAndSwitchCurrent()\n", Name()));
6352 
6353 	if (!fOwner)
6354 		return;
6355 
6356 	fOwner->check_lock();
6357 
6358 	_SwitchServerCurrentView();
6359 }
6360 
6361 
6362 void
6363 BView::_CheckLock() const
6364 {
6365 	if (fOwner)
6366 		fOwner->check_lock();
6367 }
6368 
6369 
6370 void
6371 BView::_SwitchServerCurrentView() const
6372 {
6373 	int32 serverToken = _get_object_token_(this);
6374 
6375 	if (fOwner->fLastViewToken != serverToken) {
6376 		STRACE(("contacting app_server... sending token: %" B_PRId32 "\n",
6377 			serverToken));
6378 		fOwner->fLink->StartMessage(AS_SET_CURRENT_VIEW);
6379 		fOwner->fLink->Attach<int32>(serverToken);
6380 
6381 		fOwner->fLastViewToken = serverToken;
6382 	}
6383 }
6384 
6385 
6386 status_t
6387 BView::ScrollWithMouseWheelDelta(BScrollBar* scrollBar, float delta)
6388 {
6389 	if (scrollBar == NULL || delta == 0.0f)
6390 		return B_BAD_VALUE;
6391 
6392 	float smallStep;
6393 	float largeStep;
6394 	scrollBar->GetSteps(&smallStep, &largeStep);
6395 
6396 	// pressing the shift key scrolls faster (following the pseudo-standard set
6397 	// by other desktop environments).
6398 	if ((modifiers() & B_SHIFT_KEY) != 0)
6399 		delta *= largeStep;
6400 	else
6401 		delta *= smallStep * 3;
6402 
6403 	scrollBar->SetValue(scrollBar->Value() + delta);
6404 
6405 	return B_OK;
6406 }
6407 
6408 
6409 #if __GNUC__ == 2
6410 
6411 
6412 extern "C" void
6413 _ReservedView1__5BView(BView* view, BRect rect)
6414 {
6415 	view->BView::DrawAfterChildren(rect);
6416 }
6417 
6418 
6419 extern "C" void
6420 _ReservedView2__5BView(BView* view)
6421 {
6422 	// MinSize()
6423 	perform_data_min_size data;
6424 	view->Perform(PERFORM_CODE_MIN_SIZE, &data);
6425 }
6426 
6427 
6428 extern "C" void
6429 _ReservedView3__5BView(BView* view)
6430 {
6431 	// MaxSize()
6432 	perform_data_max_size data;
6433 	view->Perform(PERFORM_CODE_MAX_SIZE, &data);
6434 }
6435 
6436 
6437 extern "C" BSize
6438 _ReservedView4__5BView(BView* view)
6439 {
6440 	// PreferredSize()
6441 	perform_data_preferred_size data;
6442 	view->Perform(PERFORM_CODE_PREFERRED_SIZE, &data);
6443 	return data.return_value;
6444 }
6445 
6446 
6447 extern "C" BAlignment
6448 _ReservedView5__5BView(BView* view)
6449 {
6450 	// LayoutAlignment()
6451 	perform_data_layout_alignment data;
6452 	view->Perform(PERFORM_CODE_LAYOUT_ALIGNMENT, &data);
6453 	return data.return_value;
6454 }
6455 
6456 
6457 extern "C" bool
6458 _ReservedView6__5BView(BView* view)
6459 {
6460 	// HasHeightForWidth()
6461 	perform_data_has_height_for_width data;
6462 	view->Perform(PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH, &data);
6463 	return data.return_value;
6464 }
6465 
6466 
6467 extern "C" void
6468 _ReservedView7__5BView(BView* view, float width, float* min, float* max,
6469 	float* preferred)
6470 {
6471 	// GetHeightForWidth()
6472 	perform_data_get_height_for_width data;
6473 	data.width = width;
6474 	view->Perform(PERFORM_CODE_GET_HEIGHT_FOR_WIDTH, &data);
6475 	if (min != NULL)
6476 		*min = data.min;
6477 	if (max != NULL)
6478 		*max = data.max;
6479 	if (preferred != NULL)
6480 		*preferred = data.preferred;
6481 }
6482 
6483 
6484 extern "C" void
6485 _ReservedView8__5BView(BView* view, BLayout* layout)
6486 {
6487 	// SetLayout()
6488 	perform_data_set_layout data;
6489 	data.layout = layout;
6490 	view->Perform(PERFORM_CODE_SET_LAYOUT, &data);
6491 }
6492 
6493 
6494 extern "C" void
6495 _ReservedView9__5BView(BView* view, bool descendants)
6496 {
6497 	// LayoutInvalidated()
6498 	perform_data_layout_invalidated data;
6499 	data.descendants = descendants;
6500 	view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
6501 }
6502 
6503 
6504 extern "C" void
6505 _ReservedView10__5BView(BView* view)
6506 {
6507 	// DoLayout()
6508 	view->Perform(PERFORM_CODE_DO_LAYOUT, NULL);
6509 }
6510 
6511 
6512 #endif	// __GNUC__ == 2
6513 
6514 
6515 extern "C" bool
6516 B_IF_GCC_2(_ReservedView11__5BView, _ZN5BView15_ReservedView11Ev)(
6517 	BView* view, BPoint point, BToolTip** _toolTip)
6518 {
6519 	// GetToolTipAt()
6520 	perform_data_get_tool_tip_at data;
6521 	data.point = point;
6522 	data.tool_tip = _toolTip;
6523 	view->Perform(PERFORM_CODE_GET_TOOL_TIP_AT, &data);
6524 	return data.return_value;
6525 }
6526 
6527 
6528 extern "C" void
6529 B_IF_GCC_2(_ReservedView12__5BView, _ZN5BView15_ReservedView12Ev)(
6530 	BView* view)
6531 {
6532 	// LayoutChanged();
6533 	view->Perform(PERFORM_CODE_LAYOUT_CHANGED, NULL);
6534 }
6535 
6536 
6537 void BView::_ReservedView13() {}
6538 void BView::_ReservedView14() {}
6539 void BView::_ReservedView15() {}
6540 void BView::_ReservedView16() {}
6541 
6542 
6543 BView::BView(const BView& other)
6544 	:
6545 	BHandler()
6546 {
6547 	// this is private and not functional, but exported
6548 }
6549 
6550 
6551 BView&
6552 BView::operator=(const BView& other)
6553 {
6554 	// this is private and not functional, but exported
6555 	return *this;
6556 }
6557 
6558 
6559 void
6560 BView::_PrintToStream()
6561 {
6562 	printf("BView::_PrintToStream()\n");
6563 	printf("\tName: %s\n"
6564 		"\tParent: %s\n"
6565 		"\tFirstChild: %s\n"
6566 		"\tNextSibling: %s\n"
6567 		"\tPrevSibling: %s\n"
6568 		"\tOwner(Window): %s\n"
6569 		"\tToken: %" B_PRId32 "\n"
6570 		"\tFlags: %" B_PRId32 "\n"
6571 		"\tView origin: (%f,%f)\n"
6572 		"\tView Bounds rectangle: (%f,%f,%f,%f)\n"
6573 		"\tShow level: %d\n"
6574 		"\tTopView?: %s\n"
6575 		"\tBPicture: %s\n"
6576 		"\tVertical Scrollbar %s\n"
6577 		"\tHorizontal Scrollbar %s\n"
6578 		"\tIs Printing?: %s\n"
6579 		"\tShelf?: %s\n"
6580 		"\tEventMask: %" B_PRId32 "\n"
6581 		"\tEventOptions: %" B_PRId32 "\n",
6582 	Name(),
6583 	fParent ? fParent->Name() : "NULL",
6584 	fFirstChild ? fFirstChild->Name() : "NULL",
6585 	fNextSibling ? fNextSibling->Name() : "NULL",
6586 	fPreviousSibling ? fPreviousSibling->Name() : "NULL",
6587 	fOwner ? fOwner->Name() : "NULL",
6588 	_get_object_token_(this),
6589 	fFlags,
6590 	fParentOffset.x, fParentOffset.y,
6591 	fBounds.left, fBounds.top, fBounds.right, fBounds.bottom,
6592 	fShowLevel,
6593 	fTopLevelView ? "YES" : "NO",
6594 	fCurrentPicture? "YES" : "NULL",
6595 	fVerScroller? "YES" : "NULL",
6596 	fHorScroller? "YES" : "NULL",
6597 	fIsPrinting? "YES" : "NO",
6598 	fShelf? "YES" : "NO",
6599 	fEventMask,
6600 	fEventOptions);
6601 
6602 	printf("\tState status:\n"
6603 		"\t\tLocalCoordianteSystem: (%f,%f)\n"
6604 		"\t\tPenLocation: (%f,%f)\n"
6605 		"\t\tPenSize: %f\n"
6606 		"\t\tHighColor: [%d,%d,%d,%d]\n"
6607 		"\t\tLowColor: [%d,%d,%d,%d]\n"
6608 		"\t\tViewColor: [%d,%d,%d,%d]\n"
6609 		"\t\tPattern: %" B_PRIx64 "\n"
6610 		"\t\tDrawingMode: %d\n"
6611 		"\t\tLineJoinMode: %d\n"
6612 		"\t\tLineCapMode: %d\n"
6613 		"\t\tMiterLimit: %f\n"
6614 		"\t\tAlphaSource: %d\n"
6615 		"\t\tAlphaFuntion: %d\n"
6616 		"\t\tScale: %f\n"
6617 		"\t\t(Print)FontAliasing: %s\n"
6618 		"\t\tFont Info:\n",
6619 	fState->origin.x, fState->origin.y,
6620 	fState->pen_location.x, fState->pen_location.y,
6621 	fState->pen_size,
6622 	fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha,
6623 	fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha,
6624 	fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha,
6625 	*((uint64*)&(fState->pattern)),
6626 	fState->drawing_mode,
6627 	fState->line_join,
6628 	fState->line_cap,
6629 	fState->miter_limit,
6630 	fState->alpha_source_mode,
6631 	fState->alpha_function_mode,
6632 	fState->scale,
6633 	fState->font_aliasing? "YES" : "NO");
6634 
6635 	fState->font.PrintToStream();
6636 
6637 	// TODO: also print the line array.
6638 }
6639 
6640 
6641 void
6642 BView::_PrintTree()
6643 {
6644 	int32 spaces = 2;
6645 	BView* c = fFirstChild; //c = short for: current
6646 	printf( "'%s'\n", Name() );
6647 	if (c != NULL) {
6648 		while(true) {
6649 			// action block
6650 			{
6651 				for (int i = 0; i < spaces; i++)
6652 					printf(" ");
6653 
6654 				printf( "'%s'\n", c->Name() );
6655 			}
6656 
6657 			// go deep
6658 			if (c->fFirstChild) {
6659 				c = c->fFirstChild;
6660 				spaces += 2;
6661 			} else {
6662 				// go right
6663 				if (c->fNextSibling) {
6664 					c = c->fNextSibling;
6665 				} else {
6666 					// go up
6667 					while (!c->fParent->fNextSibling && c->fParent != this) {
6668 						c = c->fParent;
6669 						spaces -= 2;
6670 					}
6671 
6672 					// that enough! We've reached this view.
6673 					if (c->fParent == this)
6674 						break;
6675 
6676 					c = c->fParent->fNextSibling;
6677 					spaces -= 2;
6678 				}
6679 			}
6680 		}
6681 	}
6682 }
6683 
6684 
6685 // #pragma mark -
6686 
6687 
6688 BLayoutItem*
6689 BView::Private::LayoutItemAt(int32 index)
6690 {
6691 	return fView->fLayoutData->fLayoutItems.ItemAt(index);
6692 }
6693 
6694 
6695 int32
6696 BView::Private::CountLayoutItems()
6697 {
6698 	return fView->fLayoutData->fLayoutItems.CountItems();
6699 }
6700 
6701 
6702 void
6703 BView::Private::RegisterLayoutItem(BLayoutItem* item)
6704 {
6705 	fView->fLayoutData->fLayoutItems.AddItem(item);
6706 }
6707 
6708 
6709 void
6710 BView::Private::DeregisterLayoutItem(BLayoutItem* item)
6711 {
6712 	fView->fLayoutData->fLayoutItems.RemoveItem(item);
6713 }
6714 
6715 
6716 bool
6717 BView::Private::MinMaxValid()
6718 {
6719 	return fView->fLayoutData->fMinMaxValid;
6720 }
6721 
6722 
6723 bool
6724 BView::Private::WillLayout()
6725 {
6726 	BView::LayoutData* data = fView->fLayoutData;
6727 	if (data->fLayoutInProgress)
6728 		return false;
6729 	if (data->fNeedsRelayout || !data->fLayoutValid || !data->fMinMaxValid)
6730 		return true;
6731 	return false;
6732 }
6733