xref: /haiku/src/kits/interface/View.cpp (revision baa739985b88a1dd05ca48ceb4b0edfdd1a5d46b)
1 /*
2  * Copyright 2001-2019 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::DrawTiledBitmapAsync(const BBitmap* bitmap, BRect viewRect,
3125 	BPoint phase)
3126 {
3127 	if (bitmap == NULL || fOwner == NULL || !viewRect.IsValid())
3128 		return;
3129 
3130 	_CheckLockAndSwitchCurrent();
3131 
3132 	ViewDrawBitmapInfo info;
3133 	info.bitmapToken = bitmap->_ServerToken();
3134 	info.options = B_TILE_BITMAP;
3135 	info.viewRect = viewRect;
3136 	info.bitmapRect = bitmap->Bounds().OffsetToCopy(phase);
3137 
3138 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3139 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3140 
3141 	_FlushIfNotInTransaction();
3142 }
3143 
3144 
3145 void
3146 BView::DrawTiledBitmap(const BBitmap* bitmap, BRect viewRect, BPoint phase)
3147 {
3148 	if (fOwner) {
3149 		DrawTiledBitmapAsync(bitmap, viewRect, phase);
3150 		Sync();
3151 	}
3152 }
3153 
3154 
3155 void
3156 BView::DrawChar(char c)
3157 {
3158 	DrawString(&c, 1, PenLocation());
3159 }
3160 
3161 
3162 void
3163 BView::DrawChar(char c, BPoint location)
3164 {
3165 	DrawString(&c, 1, location);
3166 }
3167 
3168 
3169 void
3170 BView::DrawString(const char* string, escapement_delta* delta)
3171 {
3172 	if (string == NULL)
3173 		return;
3174 
3175 	DrawString(string, strlen(string), PenLocation(), delta);
3176 }
3177 
3178 
3179 void
3180 BView::DrawString(const char* string, BPoint location, escapement_delta* delta)
3181 {
3182 	if (string == NULL)
3183 		return;
3184 
3185 	DrawString(string, strlen(string), location, delta);
3186 }
3187 
3188 
3189 void
3190 BView::DrawString(const char* string, int32 length, escapement_delta* delta)
3191 {
3192 	DrawString(string, length, PenLocation(), delta);
3193 }
3194 
3195 
3196 void
3197 BView::DrawString(const char* string, int32 length, BPoint location,
3198 	escapement_delta* delta)
3199 {
3200 	if (fOwner == NULL || string == NULL || length < 1)
3201 		return;
3202 
3203 	_CheckLockAndSwitchCurrent();
3204 
3205 	ViewDrawStringInfo info;
3206 	info.stringLength = length;
3207 	info.location = location;
3208 	if (delta != NULL)
3209 		info.delta = *delta;
3210 
3211 	// quite often delta will be NULL
3212 	if (delta)
3213 		fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_DELTA);
3214 	else
3215 		fOwner->fLink->StartMessage(AS_DRAW_STRING);
3216 
3217 	fOwner->fLink->Attach<ViewDrawStringInfo>(info);
3218 	fOwner->fLink->Attach(string, length);
3219 
3220 	_FlushIfNotInTransaction();
3221 
3222 	// this modifies our pen location, so we invalidate the flag.
3223 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3224 }
3225 
3226 
3227 void
3228 BView::DrawString(const char* string, const BPoint* locations,
3229 	int32 locationCount)
3230 {
3231 	if (string == NULL)
3232 		return;
3233 
3234 	DrawString(string, strlen(string), locations, locationCount);
3235 }
3236 
3237 
3238 void
3239 BView::DrawString(const char* string, int32 length, const BPoint* locations,
3240 	int32 locationCount)
3241 {
3242 	if (fOwner == NULL || string == NULL || length < 1 || locations == NULL)
3243 		return;
3244 
3245 	_CheckLockAndSwitchCurrent();
3246 
3247 	fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_OFFSETS);
3248 
3249 	fOwner->fLink->Attach<int32>(length);
3250 	fOwner->fLink->Attach<int32>(locationCount);
3251 	fOwner->fLink->Attach(string, length);
3252 	fOwner->fLink->Attach(locations, locationCount * sizeof(BPoint));
3253 
3254 	_FlushIfNotInTransaction();
3255 
3256 	// this modifies our pen location, so we invalidate the flag.
3257 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3258 }
3259 
3260 
3261 void
3262 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius,
3263 	::pattern pattern)
3264 {
3265 	StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius,
3266 		center.x + xRadius, center.y + yRadius), pattern);
3267 }
3268 
3269 
3270 void
3271 BView::StrokeEllipse(BRect rect, ::pattern pattern)
3272 {
3273 	if (fOwner == NULL)
3274 		return;
3275 
3276 	_CheckLockAndSwitchCurrent();
3277 	_UpdatePattern(pattern);
3278 
3279 	fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE);
3280 	fOwner->fLink->Attach<BRect>(rect);
3281 
3282 	_FlushIfNotInTransaction();
3283 }
3284 
3285 
3286 void
3287 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3288 	::pattern pattern)
3289 {
3290 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3291 		center.x + xRadius, center.y + yRadius), pattern);
3292 }
3293 
3294 
3295 void
3296 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3297 	const BGradient& gradient)
3298 {
3299 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3300 		center.x + xRadius, center.y + yRadius), gradient);
3301 }
3302 
3303 
3304 void
3305 BView::FillEllipse(BRect rect, ::pattern pattern)
3306 {
3307 	if (fOwner == NULL)
3308 		return;
3309 
3310 	_CheckLockAndSwitchCurrent();
3311 	_UpdatePattern(pattern);
3312 
3313 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE);
3314 	fOwner->fLink->Attach<BRect>(rect);
3315 
3316 	_FlushIfNotInTransaction();
3317 }
3318 
3319 
3320 void
3321 BView::FillEllipse(BRect rect, const BGradient& gradient)
3322 {
3323 	if (fOwner == NULL)
3324 		return;
3325 
3326 	_CheckLockAndSwitchCurrent();
3327 
3328 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE_GRADIENT);
3329 	fOwner->fLink->Attach<BRect>(rect);
3330 	fOwner->fLink->AttachGradient(gradient);
3331 
3332 	_FlushIfNotInTransaction();
3333 }
3334 
3335 
3336 void
3337 BView::StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle,
3338 	float arcAngle, ::pattern pattern)
3339 {
3340 	StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3341 		center.y + yRadius), startAngle, arcAngle, pattern);
3342 }
3343 
3344 
3345 void
3346 BView::StrokeArc(BRect rect, float startAngle, float arcAngle,
3347 	::pattern pattern)
3348 {
3349 	if (fOwner == NULL)
3350 		return;
3351 
3352 	_CheckLockAndSwitchCurrent();
3353 	_UpdatePattern(pattern);
3354 
3355 	fOwner->fLink->StartMessage(AS_STROKE_ARC);
3356 	fOwner->fLink->Attach<BRect>(rect);
3357 	fOwner->fLink->Attach<float>(startAngle);
3358 	fOwner->fLink->Attach<float>(arcAngle);
3359 
3360 	_FlushIfNotInTransaction();
3361 }
3362 
3363 
3364 void
3365 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3366 	float arcAngle, ::pattern pattern)
3367 {
3368 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3369 		center.y + yRadius), startAngle, arcAngle, pattern);
3370 }
3371 
3372 
3373 void
3374 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3375 	float arcAngle, const BGradient& gradient)
3376 {
3377 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3378 		center.y + yRadius), startAngle, arcAngle, gradient);
3379 }
3380 
3381 
3382 void
3383 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3384 	::pattern pattern)
3385 {
3386 	if (fOwner == NULL)
3387 		return;
3388 
3389 	_CheckLockAndSwitchCurrent();
3390 	_UpdatePattern(pattern);
3391 
3392 	fOwner->fLink->StartMessage(AS_FILL_ARC);
3393 	fOwner->fLink->Attach<BRect>(rect);
3394 	fOwner->fLink->Attach<float>(startAngle);
3395 	fOwner->fLink->Attach<float>(arcAngle);
3396 
3397 	_FlushIfNotInTransaction();
3398 }
3399 
3400 
3401 void
3402 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3403 	const BGradient& gradient)
3404 {
3405 	if (fOwner == NULL)
3406 		return;
3407 
3408 	_CheckLockAndSwitchCurrent();
3409 
3410 	fOwner->fLink->StartMessage(AS_FILL_ARC_GRADIENT);
3411 	fOwner->fLink->Attach<BRect>(rect);
3412 	fOwner->fLink->Attach<float>(startAngle);
3413 	fOwner->fLink->Attach<float>(arcAngle);
3414 	fOwner->fLink->AttachGradient(gradient);
3415 
3416 	_FlushIfNotInTransaction();
3417 }
3418 
3419 
3420 void
3421 BView::StrokeBezier(BPoint* controlPoints, ::pattern pattern)
3422 {
3423 	if (fOwner == NULL)
3424 		return;
3425 
3426 	_CheckLockAndSwitchCurrent();
3427 	_UpdatePattern(pattern);
3428 
3429 	fOwner->fLink->StartMessage(AS_STROKE_BEZIER);
3430 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3431 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3432 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3433 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3434 
3435 	_FlushIfNotInTransaction();
3436 }
3437 
3438 
3439 void
3440 BView::FillBezier(BPoint* controlPoints, ::pattern pattern)
3441 {
3442 	if (fOwner == NULL)
3443 		return;
3444 
3445 	_CheckLockAndSwitchCurrent();
3446 	_UpdatePattern(pattern);
3447 
3448 	fOwner->fLink->StartMessage(AS_FILL_BEZIER);
3449 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3450 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3451 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3452 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3453 
3454 	_FlushIfNotInTransaction();
3455 }
3456 
3457 
3458 void
3459 BView::FillBezier(BPoint* controlPoints, const BGradient& gradient)
3460 {
3461 	if (fOwner == NULL)
3462 		return;
3463 
3464 	_CheckLockAndSwitchCurrent();
3465 
3466 	fOwner->fLink->StartMessage(AS_FILL_BEZIER_GRADIENT);
3467 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3468 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3469 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3470 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3471 	fOwner->fLink->AttachGradient(gradient);
3472 
3473 	_FlushIfNotInTransaction();
3474 }
3475 
3476 
3477 void
3478 BView::StrokePolygon(const BPolygon* polygon, bool closed, ::pattern pattern)
3479 {
3480 	if (polygon == NULL)
3481 		return;
3482 
3483 	StrokePolygon(polygon->fPoints, polygon->fCount, polygon->Frame(), closed,
3484 		pattern);
3485 }
3486 
3487 
3488 void
3489 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
3490 	::pattern pattern)
3491 {
3492 	BPolygon polygon(pointArray, numPoints);
3493 
3494 	StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed,
3495 		pattern);
3496 }
3497 
3498 
3499 void
3500 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3501 	bool closed, ::pattern pattern)
3502 {
3503 	if (pointArray == NULL
3504 		|| numPoints <= 1
3505 		|| fOwner == NULL)
3506 		return;
3507 
3508 	_CheckLockAndSwitchCurrent();
3509 	_UpdatePattern(pattern);
3510 
3511 	BPolygon polygon(pointArray, numPoints);
3512 	polygon.MapTo(polygon.Frame(), bounds);
3513 
3514 	if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON,
3515 			polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool)
3516 				+ sizeof(int32)) == B_OK) {
3517 		fOwner->fLink->Attach<BRect>(polygon.Frame());
3518 		fOwner->fLink->Attach<bool>(closed);
3519 		fOwner->fLink->Attach<int32>(polygon.fCount);
3520 		fOwner->fLink->Attach(polygon.fPoints, polygon.fCount * sizeof(BPoint));
3521 
3522 		_FlushIfNotInTransaction();
3523 	} else {
3524 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3525 	}
3526 }
3527 
3528 
3529 void
3530 BView::FillPolygon(const BPolygon* polygon, ::pattern pattern)
3531 {
3532 	if (polygon == NULL
3533 		|| polygon->fCount <= 2
3534 		|| fOwner == NULL)
3535 		return;
3536 
3537 	_CheckLockAndSwitchCurrent();
3538 	_UpdatePattern(pattern);
3539 
3540 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON,
3541 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3542 				== B_OK) {
3543 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3544 		fOwner->fLink->Attach<int32>(polygon->fCount);
3545 		fOwner->fLink->Attach(polygon->fPoints,
3546 			polygon->fCount * sizeof(BPoint));
3547 
3548 		_FlushIfNotInTransaction();
3549 	} else {
3550 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3551 	}
3552 }
3553 
3554 
3555 void
3556 BView::FillPolygon(const BPolygon* polygon, const BGradient& gradient)
3557 {
3558 	if (polygon == NULL
3559 		|| polygon->fCount <= 2
3560 		|| fOwner == NULL)
3561 		return;
3562 
3563 	_CheckLockAndSwitchCurrent();
3564 
3565 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON_GRADIENT,
3566 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3567 				== B_OK) {
3568 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3569 		fOwner->fLink->Attach<int32>(polygon->fCount);
3570 		fOwner->fLink->Attach(polygon->fPoints,
3571 			polygon->fCount * sizeof(BPoint));
3572 		fOwner->fLink->AttachGradient(gradient);
3573 
3574 		_FlushIfNotInTransaction();
3575 	} else {
3576 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3577 	}
3578 }
3579 
3580 
3581 void
3582 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern)
3583 {
3584 	if (pointArray == NULL)
3585 		return;
3586 
3587 	BPolygon polygon(pointArray, numPoints);
3588 	FillPolygon(&polygon, pattern);
3589 }
3590 
3591 
3592 void
3593 BView::FillPolygon(const BPoint* pointArray, int32 numPoints,
3594 	const BGradient& gradient)
3595 {
3596 	if (pointArray == NULL)
3597 		return;
3598 
3599 	BPolygon polygon(pointArray, numPoints);
3600 	FillPolygon(&polygon, gradient);
3601 }
3602 
3603 
3604 void
3605 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3606 	::pattern pattern)
3607 {
3608 	if (pointArray == NULL)
3609 		return;
3610 
3611 	BPolygon polygon(pointArray, numPoints);
3612 
3613 	polygon.MapTo(polygon.Frame(), bounds);
3614 	FillPolygon(&polygon, pattern);
3615 }
3616 
3617 
3618 void
3619 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3620 	const BGradient& gradient)
3621 {
3622 	if (pointArray == NULL)
3623 		return;
3624 
3625 	BPolygon polygon(pointArray, numPoints);
3626 
3627 	polygon.MapTo(polygon.Frame(), bounds);
3628 	FillPolygon(&polygon, gradient);
3629 }
3630 
3631 
3632 void
3633 BView::StrokeRect(BRect rect, ::pattern pattern)
3634 {
3635 	if (fOwner == NULL)
3636 		return;
3637 
3638 	_CheckLockAndSwitchCurrent();
3639 	_UpdatePattern(pattern);
3640 
3641 	fOwner->fLink->StartMessage(AS_STROKE_RECT);
3642 	fOwner->fLink->Attach<BRect>(rect);
3643 
3644 	_FlushIfNotInTransaction();
3645 }
3646 
3647 
3648 void
3649 BView::FillRect(BRect rect, ::pattern pattern)
3650 {
3651 	if (fOwner == NULL)
3652 		return;
3653 
3654 	// NOTE: ensuring compatibility with R5,
3655 	// invalid rects are not filled, they are stroked though!
3656 	if (!rect.IsValid())
3657 		return;
3658 
3659 	_CheckLockAndSwitchCurrent();
3660 	_UpdatePattern(pattern);
3661 
3662 	fOwner->fLink->StartMessage(AS_FILL_RECT);
3663 	fOwner->fLink->Attach<BRect>(rect);
3664 
3665 	_FlushIfNotInTransaction();
3666 }
3667 
3668 
3669 void
3670 BView::FillRect(BRect rect, const BGradient& gradient)
3671 {
3672 	if (fOwner == NULL)
3673 		return;
3674 
3675 	// NOTE: ensuring compatibility with R5,
3676 	// invalid rects are not filled, they are stroked though!
3677 	if (!rect.IsValid())
3678 		return;
3679 
3680 	_CheckLockAndSwitchCurrent();
3681 
3682 	fOwner->fLink->StartMessage(AS_FILL_RECT_GRADIENT);
3683 	fOwner->fLink->Attach<BRect>(rect);
3684 	fOwner->fLink->AttachGradient(gradient);
3685 
3686 	_FlushIfNotInTransaction();
3687 }
3688 
3689 
3690 void
3691 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius,
3692 	::pattern pattern)
3693 {
3694 	if (fOwner == NULL)
3695 		return;
3696 
3697 	_CheckLockAndSwitchCurrent();
3698 	_UpdatePattern(pattern);
3699 
3700 	fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT);
3701 	fOwner->fLink->Attach<BRect>(rect);
3702 	fOwner->fLink->Attach<float>(xRadius);
3703 	fOwner->fLink->Attach<float>(yRadius);
3704 
3705 	_FlushIfNotInTransaction();
3706 }
3707 
3708 
3709 void
3710 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3711 	::pattern pattern)
3712 {
3713 	if (fOwner == NULL)
3714 		return;
3715 
3716 	_CheckLockAndSwitchCurrent();
3717 
3718 	_UpdatePattern(pattern);
3719 
3720 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT);
3721 	fOwner->fLink->Attach<BRect>(rect);
3722 	fOwner->fLink->Attach<float>(xRadius);
3723 	fOwner->fLink->Attach<float>(yRadius);
3724 
3725 	_FlushIfNotInTransaction();
3726 }
3727 
3728 
3729 void
3730 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3731 	const BGradient& gradient)
3732 {
3733 	if (fOwner == NULL)
3734 		return;
3735 
3736 	_CheckLockAndSwitchCurrent();
3737 
3738 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT_GRADIENT);
3739 	fOwner->fLink->Attach<BRect>(rect);
3740 	fOwner->fLink->Attach<float>(xRadius);
3741 	fOwner->fLink->Attach<float>(yRadius);
3742 	fOwner->fLink->AttachGradient(gradient);
3743 
3744 	_FlushIfNotInTransaction();
3745 }
3746 
3747 
3748 void
3749 BView::FillRegion(BRegion* region, ::pattern pattern)
3750 {
3751 	if (region == NULL || fOwner == NULL)
3752 		return;
3753 
3754 	_CheckLockAndSwitchCurrent();
3755 
3756 	_UpdatePattern(pattern);
3757 
3758 	fOwner->fLink->StartMessage(AS_FILL_REGION);
3759 	fOwner->fLink->AttachRegion(*region);
3760 
3761 	_FlushIfNotInTransaction();
3762 }
3763 
3764 
3765 void
3766 BView::FillRegion(BRegion* region, const BGradient& gradient)
3767 {
3768 	if (region == NULL || fOwner == NULL)
3769 		return;
3770 
3771 	_CheckLockAndSwitchCurrent();
3772 
3773 	fOwner->fLink->StartMessage(AS_FILL_REGION_GRADIENT);
3774 	fOwner->fLink->AttachRegion(*region);
3775 	fOwner->fLink->AttachGradient(gradient);
3776 
3777 	_FlushIfNotInTransaction();
3778 }
3779 
3780 
3781 void
3782 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
3783 	::pattern pattern)
3784 {
3785 	if (fOwner == NULL)
3786 		return;
3787 
3788 	_CheckLockAndSwitchCurrent();
3789 
3790 	_UpdatePattern(pattern);
3791 
3792 	fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE);
3793 	fOwner->fLink->Attach<BPoint>(point1);
3794 	fOwner->fLink->Attach<BPoint>(point2);
3795 	fOwner->fLink->Attach<BPoint>(point3);
3796 	fOwner->fLink->Attach<BRect>(bounds);
3797 
3798 	_FlushIfNotInTransaction();
3799 }
3800 
3801 
3802 void
3803 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3,
3804 	::pattern pattern)
3805 {
3806 	if (fOwner) {
3807 		// we construct the smallest rectangle that contains the 3 points
3808 		// for the 1st point
3809 		BRect bounds(point1, point1);
3810 
3811 		// for the 2nd point
3812 		if (point2.x < bounds.left)
3813 			bounds.left = point2.x;
3814 
3815 		if (point2.y < bounds.top)
3816 			bounds.top = point2.y;
3817 
3818 		if (point2.x > bounds.right)
3819 			bounds.right = point2.x;
3820 
3821 		if (point2.y > bounds.bottom)
3822 			bounds.bottom = point2.y;
3823 
3824 		// for the 3rd point
3825 		if (point3.x < bounds.left)
3826 			bounds.left = point3.x;
3827 
3828 		if (point3.y < bounds.top)
3829 			bounds.top = point3.y;
3830 
3831 		if (point3.x > bounds.right)
3832 			bounds.right = point3.x;
3833 
3834 		if (point3.y > bounds.bottom)
3835 			bounds.bottom = point3.y;
3836 
3837 		StrokeTriangle(point1, point2, point3, bounds, pattern);
3838 	}
3839 }
3840 
3841 
3842 void
3843 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3844 	::pattern pattern)
3845 {
3846 	if (fOwner) {
3847 		// we construct the smallest rectangle that contains the 3 points
3848 		// for the 1st point
3849 		BRect bounds(point1, point1);
3850 
3851 		// for the 2nd point
3852 		if (point2.x < bounds.left)
3853 			bounds.left = point2.x;
3854 
3855 		if (point2.y < bounds.top)
3856 			bounds.top = point2.y;
3857 
3858 		if (point2.x > bounds.right)
3859 			bounds.right = point2.x;
3860 
3861 		if (point2.y > bounds.bottom)
3862 			bounds.bottom = point2.y;
3863 
3864 		// for the 3rd point
3865 		if (point3.x < bounds.left)
3866 			bounds.left = point3.x;
3867 
3868 		if (point3.y < bounds.top)
3869 			bounds.top = point3.y;
3870 
3871 		if (point3.x > bounds.right)
3872 			bounds.right = point3.x;
3873 
3874 		if (point3.y > bounds.bottom)
3875 			bounds.bottom = point3.y;
3876 
3877 		FillTriangle(point1, point2, point3, bounds, pattern);
3878 	}
3879 }
3880 
3881 
3882 void
3883 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3884 	const BGradient& gradient)
3885 {
3886 	if (fOwner) {
3887 		// we construct the smallest rectangle that contains the 3 points
3888 		// for the 1st point
3889 		BRect bounds(point1, point1);
3890 
3891 		// for the 2nd point
3892 		if (point2.x < bounds.left)
3893 			bounds.left = point2.x;
3894 
3895 		if (point2.y < bounds.top)
3896 			bounds.top = point2.y;
3897 
3898 		if (point2.x > bounds.right)
3899 			bounds.right = point2.x;
3900 
3901 		if (point2.y > bounds.bottom)
3902 			bounds.bottom = point2.y;
3903 
3904 		// for the 3rd point
3905 		if (point3.x < bounds.left)
3906 			bounds.left = point3.x;
3907 
3908 		if (point3.y < bounds.top)
3909 			bounds.top = point3.y;
3910 
3911 		if (point3.x > bounds.right)
3912 			bounds.right = point3.x;
3913 
3914 		if (point3.y > bounds.bottom)
3915 			bounds.bottom = point3.y;
3916 
3917 		FillTriangle(point1, point2, point3, bounds, gradient);
3918 	}
3919 }
3920 
3921 
3922 void
3923 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3924 	BRect bounds, ::pattern pattern)
3925 {
3926 	if (fOwner == NULL)
3927 		return;
3928 
3929 	_CheckLockAndSwitchCurrent();
3930 	_UpdatePattern(pattern);
3931 
3932 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE);
3933 	fOwner->fLink->Attach<BPoint>(point1);
3934 	fOwner->fLink->Attach<BPoint>(point2);
3935 	fOwner->fLink->Attach<BPoint>(point3);
3936 	fOwner->fLink->Attach<BRect>(bounds);
3937 
3938 	_FlushIfNotInTransaction();
3939 }
3940 
3941 
3942 void
3943 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
3944 	const BGradient& gradient)
3945 {
3946 	if (fOwner == NULL)
3947 		return;
3948 
3949 	_CheckLockAndSwitchCurrent();
3950 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE_GRADIENT);
3951 	fOwner->fLink->Attach<BPoint>(point1);
3952 	fOwner->fLink->Attach<BPoint>(point2);
3953 	fOwner->fLink->Attach<BPoint>(point3);
3954 	fOwner->fLink->Attach<BRect>(bounds);
3955 	fOwner->fLink->AttachGradient(gradient);
3956 
3957 	_FlushIfNotInTransaction();
3958 }
3959 
3960 
3961 void
3962 BView::StrokeLine(BPoint toPoint, ::pattern pattern)
3963 {
3964 	StrokeLine(PenLocation(), toPoint, pattern);
3965 }
3966 
3967 
3968 void
3969 BView::StrokeLine(BPoint start, BPoint end, ::pattern pattern)
3970 {
3971 	if (fOwner == NULL)
3972 		return;
3973 
3974 	_CheckLockAndSwitchCurrent();
3975 	_UpdatePattern(pattern);
3976 
3977 	ViewStrokeLineInfo info;
3978 	info.startPoint = start;
3979 	info.endPoint = end;
3980 
3981 	fOwner->fLink->StartMessage(AS_STROKE_LINE);
3982 	fOwner->fLink->Attach<ViewStrokeLineInfo>(info);
3983 
3984 	_FlushIfNotInTransaction();
3985 
3986 	// this modifies our pen location, so we invalidate the flag.
3987 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3988 }
3989 
3990 
3991 void
3992 BView::StrokeShape(BShape* shape, ::pattern pattern)
3993 {
3994 	if (shape == NULL || fOwner == NULL)
3995 		return;
3996 
3997 	shape_data* sd = (shape_data*)shape->fPrivateData;
3998 	if (sd->opCount == 0 || sd->ptCount == 0)
3999 		return;
4000 
4001 	_CheckLockAndSwitchCurrent();
4002 	_UpdatePattern(pattern);
4003 
4004 	fOwner->fLink->StartMessage(AS_STROKE_SHAPE);
4005 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4006 	fOwner->fLink->Attach<int32>(sd->opCount);
4007 	fOwner->fLink->Attach<int32>(sd->ptCount);
4008 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32));
4009 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
4010 
4011 	_FlushIfNotInTransaction();
4012 }
4013 
4014 
4015 void
4016 BView::FillShape(BShape* shape, ::pattern pattern)
4017 {
4018 	if (shape == NULL || fOwner == NULL)
4019 		return;
4020 
4021 	shape_data* sd = (shape_data*)(shape->fPrivateData);
4022 	if (sd->opCount == 0 || sd->ptCount == 0)
4023 		return;
4024 
4025 	_CheckLockAndSwitchCurrent();
4026 	_UpdatePattern(pattern);
4027 
4028 	fOwner->fLink->StartMessage(AS_FILL_SHAPE);
4029 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4030 	fOwner->fLink->Attach<int32>(sd->opCount);
4031 	fOwner->fLink->Attach<int32>(sd->ptCount);
4032 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32));
4033 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
4034 
4035 	_FlushIfNotInTransaction();
4036 }
4037 
4038 
4039 void
4040 BView::FillShape(BShape* shape, const BGradient& gradient)
4041 {
4042 	if (shape == NULL || fOwner == NULL)
4043 		return;
4044 
4045 	shape_data* sd = (shape_data*)(shape->fPrivateData);
4046 	if (sd->opCount == 0 || sd->ptCount == 0)
4047 		return;
4048 
4049 	_CheckLockAndSwitchCurrent();
4050 
4051 	fOwner->fLink->StartMessage(AS_FILL_SHAPE_GRADIENT);
4052 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4053 	fOwner->fLink->Attach<int32>(sd->opCount);
4054 	fOwner->fLink->Attach<int32>(sd->ptCount);
4055 	fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32));
4056 	fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
4057 	fOwner->fLink->AttachGradient(gradient);
4058 
4059 	_FlushIfNotInTransaction();
4060 }
4061 
4062 
4063 void
4064 BView::BeginLineArray(int32 count)
4065 {
4066 	if (fOwner == NULL)
4067 		return;
4068 
4069 	if (count <= 0)
4070 		debugger("Calling BeginLineArray with a count <= 0");
4071 
4072 	_CheckLock();
4073 
4074 	if (fCommArray) {
4075 		debugger("Can't nest BeginLineArray calls");
4076 			// not fatal, but it helps during
4077 			// development of your app and is in
4078 			// line with R5...
4079 		delete[] fCommArray->array;
4080 		delete fCommArray;
4081 	}
4082 
4083 	// TODO: since this method cannot return failure, and further AddLine()
4084 	//	calls with a NULL fCommArray would drop into the debugger anyway,
4085 	//	we allow the possible std::bad_alloc exceptions here...
4086 	fCommArray = new _array_data_;
4087 	fCommArray->count = 0;
4088 
4089 	// Make sure the fCommArray is initialized to reasonable values in cases of
4090 	// bad_alloc. At least the exception can be caught and EndLineArray won't
4091 	// crash.
4092 	fCommArray->array = NULL;
4093 	fCommArray->maxCount = 0;
4094 
4095 	fCommArray->array = new ViewLineArrayInfo[count];
4096 	fCommArray->maxCount = count;
4097 }
4098 
4099 
4100 void
4101 BView::AddLine(BPoint start, BPoint end, rgb_color color)
4102 {
4103 	if (fOwner == NULL)
4104 		return;
4105 
4106 	if (!fCommArray)
4107 		debugger("BeginLineArray must be called before using AddLine");
4108 
4109 	_CheckLock();
4110 
4111 	const uint32 &arrayCount = fCommArray->count;
4112 	if (arrayCount < fCommArray->maxCount) {
4113 		fCommArray->array[arrayCount].startPoint = start;
4114 		fCommArray->array[arrayCount].endPoint = end;
4115 		fCommArray->array[arrayCount].color = color;
4116 
4117 		fCommArray->count++;
4118 	}
4119 }
4120 
4121 
4122 void
4123 BView::EndLineArray()
4124 {
4125 	if (fOwner == NULL)
4126 		return;
4127 
4128 	if (fCommArray == NULL)
4129 		debugger("Can't call EndLineArray before BeginLineArray");
4130 
4131 	_CheckLockAndSwitchCurrent();
4132 
4133 	fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY);
4134 	fOwner->fLink->Attach<int32>(fCommArray->count);
4135 	fOwner->fLink->Attach(fCommArray->array,
4136 		fCommArray->count * sizeof(ViewLineArrayInfo));
4137 
4138 	_FlushIfNotInTransaction();
4139 
4140 	_RemoveCommArray();
4141 }
4142 
4143 
4144 void
4145 BView::SetDiskMode(char* filename, long offset)
4146 {
4147 	// TODO: implement
4148 	// One BeBook version has this to say about SetDiskMode():
4149 	//
4150 	// "Begins recording a picture to the file with the given filename
4151 	// at the given offset. Subsequent drawing commands sent to the view
4152 	// will be written to the file until EndPicture() is called. The
4153 	// stored commands may be played from the file with DrawPicture()."
4154 }
4155 
4156 
4157 void
4158 BView::BeginPicture(BPicture* picture)
4159 {
4160 	if (_CheckOwnerLockAndSwitchCurrent()
4161 		&& picture && picture->fUsurped == NULL) {
4162 		picture->Usurp(fCurrentPicture);
4163 		fCurrentPicture = picture;
4164 
4165 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_PICTURE);
4166 	}
4167 }
4168 
4169 
4170 void
4171 BView::AppendToPicture(BPicture* picture)
4172 {
4173 	_CheckLockAndSwitchCurrent();
4174 
4175 	if (picture && picture->fUsurped == NULL) {
4176 		int32 token = picture->Token();
4177 
4178 		if (token == -1) {
4179 			BeginPicture(picture);
4180 		} else {
4181 			picture->SetToken(-1);
4182 			picture->Usurp(fCurrentPicture);
4183 			fCurrentPicture = picture;
4184 			fOwner->fLink->StartMessage(AS_VIEW_APPEND_TO_PICTURE);
4185 			fOwner->fLink->Attach<int32>(token);
4186 		}
4187 	}
4188 }
4189 
4190 
4191 BPicture*
4192 BView::EndPicture()
4193 {
4194 	if (_CheckOwnerLockAndSwitchCurrent() && fCurrentPicture) {
4195 		int32 token;
4196 
4197 		fOwner->fLink->StartMessage(AS_VIEW_END_PICTURE);
4198 
4199 		int32 code;
4200 		if (fOwner->fLink->FlushWithReply(code) == B_OK
4201 			&& code == B_OK
4202 			&& fOwner->fLink->Read<int32>(&token) == B_OK) {
4203 			BPicture* picture = fCurrentPicture;
4204 			fCurrentPicture = picture->StepDown();
4205 			picture->SetToken(token);
4206 
4207 			// TODO do this more efficient e.g. use a shared area and let the
4208 			// client write into it
4209 			picture->_Download();
4210 			return picture;
4211 		}
4212 	}
4213 
4214 	return NULL;
4215 }
4216 
4217 
4218 void
4219 BView::SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
4220 	uint32 followFlags, uint32 options)
4221 {
4222 	_SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options);
4223 }
4224 
4225 
4226 void
4227 BView::SetViewBitmap(const BBitmap* bitmap, uint32 followFlags, uint32 options)
4228 {
4229 	BRect rect;
4230  	if (bitmap)
4231 		rect = bitmap->Bounds();
4232 
4233  	rect.OffsetTo(B_ORIGIN);
4234 
4235 	_SetViewBitmap(bitmap, rect, rect, followFlags, options);
4236 }
4237 
4238 
4239 void
4240 BView::ClearViewBitmap()
4241 {
4242 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4243 }
4244 
4245 
4246 status_t
4247 BView::SetViewOverlay(const BBitmap* overlay, BRect srcRect, BRect dstRect,
4248 	rgb_color* colorKey, uint32 followFlags, uint32 options)
4249 {
4250 	if (overlay == NULL || (overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0)
4251 		return B_BAD_VALUE;
4252 
4253 	status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags,
4254 		options | AS_REQUEST_COLOR_KEY);
4255 	if (status == B_OK) {
4256 		// read the color that will be treated as transparent
4257 		fOwner->fLink->Read<rgb_color>(colorKey);
4258 	}
4259 
4260 	return status;
4261 }
4262 
4263 
4264 status_t
4265 BView::SetViewOverlay(const BBitmap* overlay, rgb_color* colorKey,
4266 	uint32 followFlags, uint32 options)
4267 {
4268 	if (overlay == NULL)
4269 		return B_BAD_VALUE;
4270 
4271 	BRect rect = overlay->Bounds();
4272  	rect.OffsetTo(B_ORIGIN);
4273 
4274 	return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options);
4275 }
4276 
4277 
4278 void
4279 BView::ClearViewOverlay()
4280 {
4281 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4282 }
4283 
4284 
4285 void
4286 BView::CopyBits(BRect src, BRect dst)
4287 {
4288 	if (fOwner == NULL)
4289 		return;
4290 
4291 	if (!src.IsValid() || !dst.IsValid())
4292 		return;
4293 
4294 	_CheckLockAndSwitchCurrent();
4295 
4296 	fOwner->fLink->StartMessage(AS_VIEW_COPY_BITS);
4297 	fOwner->fLink->Attach<BRect>(src);
4298 	fOwner->fLink->Attach<BRect>(dst);
4299 
4300 	_FlushIfNotInTransaction();
4301 }
4302 
4303 
4304 void
4305 BView::DrawPicture(const BPicture* picture)
4306 {
4307 	if (picture == NULL)
4308 		return;
4309 
4310 	DrawPictureAsync(picture, PenLocation());
4311 	Sync();
4312 }
4313 
4314 
4315 void
4316 BView::DrawPicture(const BPicture* picture, BPoint where)
4317 {
4318 	if (picture == NULL)
4319 		return;
4320 
4321 	DrawPictureAsync(picture, where);
4322 	Sync();
4323 }
4324 
4325 
4326 void
4327 BView::DrawPicture(const char* filename, long offset, BPoint where)
4328 {
4329 	if (!filename)
4330 		return;
4331 
4332 	DrawPictureAsync(filename, offset, where);
4333 	Sync();
4334 }
4335 
4336 
4337 void
4338 BView::DrawPictureAsync(const BPicture* picture)
4339 {
4340 	if (picture == NULL)
4341 		return;
4342 
4343 	DrawPictureAsync(picture, PenLocation());
4344 }
4345 
4346 
4347 void
4348 BView::DrawPictureAsync(const BPicture* picture, BPoint where)
4349 {
4350 	if (picture == NULL)
4351 		return;
4352 
4353 	if (_CheckOwnerLockAndSwitchCurrent() && picture->Token() > 0) {
4354 		fOwner->fLink->StartMessage(AS_VIEW_DRAW_PICTURE);
4355 		fOwner->fLink->Attach<int32>(picture->Token());
4356 		fOwner->fLink->Attach<BPoint>(where);
4357 
4358 		_FlushIfNotInTransaction();
4359 	}
4360 }
4361 
4362 
4363 void
4364 BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
4365 {
4366 	if (!filename)
4367 		return;
4368 
4369 	// TODO: Test
4370 	BFile file(filename, B_READ_ONLY);
4371 	if (file.InitCheck() < B_OK)
4372 		return;
4373 
4374 	file.Seek(offset, SEEK_SET);
4375 
4376 	BPicture picture;
4377 	if (picture.Unflatten(&file) < B_OK)
4378 		return;
4379 
4380 	DrawPictureAsync(&picture, where);
4381 }
4382 
4383 
4384 void
4385 BView::BeginLayer(uint8 opacity)
4386 {
4387 	if (_CheckOwnerLockAndSwitchCurrent()) {
4388 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_LAYER);
4389 		fOwner->fLink->Attach<uint8>(opacity);
4390 		_FlushIfNotInTransaction();
4391 	}
4392 }
4393 
4394 
4395 void
4396 BView::EndLayer()
4397 {
4398 	if (_CheckOwnerLockAndSwitchCurrent()) {
4399 		fOwner->fLink->StartMessage(AS_VIEW_END_LAYER);
4400 		_FlushIfNotInTransaction();
4401 	}
4402 }
4403 
4404 
4405 void
4406 BView::Invalidate(BRect invalRect)
4407 {
4408 	if (fOwner == NULL)
4409 		return;
4410 
4411 	// NOTE: This rounding of the invalid rect is to stay compatible with BeOS.
4412 	// On the server side, the invalid rect will be converted to a BRegion,
4413 	// which rounds in a different manner, so that it really includes the
4414 	// fractional coordinates of a BRect (ie ceilf(rect.right) &
4415 	// ceilf(rect.bottom)), which is also what BeOS does. So we have to do the
4416 	// different rounding here to stay compatible in both ways.
4417 	invalRect.left = (int)invalRect.left;
4418 	invalRect.top = (int)invalRect.top;
4419 	invalRect.right = (int)invalRect.right;
4420 	invalRect.bottom = (int)invalRect.bottom;
4421 	if (!invalRect.IsValid())
4422 		return;
4423 
4424 	_CheckLockAndSwitchCurrent();
4425 
4426 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_RECT);
4427 	fOwner->fLink->Attach<BRect>(invalRect);
4428 
4429 // TODO: determine why this check isn't working correctly.
4430 #if 0
4431 	if (!fOwner->fUpdateRequested) {
4432 		fOwner->fLink->Flush();
4433 		fOwner->fUpdateRequested = true;
4434 	}
4435 #else
4436 	fOwner->fLink->Flush();
4437 #endif
4438 }
4439 
4440 
4441 void
4442 BView::Invalidate(const BRegion* region)
4443 {
4444 	if (region == NULL || fOwner == NULL)
4445 		return;
4446 
4447 	_CheckLockAndSwitchCurrent();
4448 
4449 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_REGION);
4450 	fOwner->fLink->AttachRegion(*region);
4451 
4452 // TODO: See above.
4453 #if 0
4454 	if (!fOwner->fUpdateRequested) {
4455 		fOwner->fLink->Flush();
4456 		fOwner->fUpdateRequested = true;
4457 	}
4458 #else
4459 	fOwner->fLink->Flush();
4460 #endif
4461 }
4462 
4463 
4464 void
4465 BView::Invalidate()
4466 {
4467 	Invalidate(Bounds());
4468 }
4469 
4470 
4471 void
4472 BView::DelayedInvalidate(bigtime_t delay)
4473 {
4474 	DelayedInvalidate(delay, Bounds());
4475 }
4476 
4477 
4478 void
4479 BView::DelayedInvalidate(bigtime_t delay, BRect invalRect)
4480 {
4481 	if (fOwner == NULL)
4482 		return;
4483 
4484 	invalRect.left = (int)invalRect.left;
4485 	invalRect.top = (int)invalRect.top;
4486 	invalRect.right = (int)invalRect.right;
4487 	invalRect.bottom = (int)invalRect.bottom;
4488 	if (!invalRect.IsValid())
4489 		return;
4490 
4491 	_CheckLockAndSwitchCurrent();
4492 
4493 	fOwner->fLink->StartMessage(AS_VIEW_DELAYED_INVALIDATE_RECT);
4494 	fOwner->fLink->Attach<bigtime_t>(system_time() + delay);
4495 	fOwner->fLink->Attach<BRect>(invalRect);
4496 	fOwner->fLink->Flush();
4497 }
4498 
4499 
4500 void
4501 BView::InvertRect(BRect rect)
4502 {
4503 	if (fOwner) {
4504 		_CheckLockAndSwitchCurrent();
4505 
4506 		fOwner->fLink->StartMessage(AS_VIEW_INVERT_RECT);
4507 		fOwner->fLink->Attach<BRect>(rect);
4508 
4509 		_FlushIfNotInTransaction();
4510 	}
4511 }
4512 
4513 
4514 //	#pragma mark - View Hierarchy Functions
4515 
4516 
4517 void
4518 BView::AddChild(BView* child, BView* before)
4519 {
4520 	STRACE(("BView(%s)::AddChild(child '%s', before '%s')\n",
4521 		this->Name(),
4522 		child != NULL && child->Name() ? child->Name() : "NULL",
4523 		before != NULL && before->Name() ? before->Name() : "NULL"));
4524 
4525 	if (!_AddChild(child, before))
4526 		return;
4527 
4528 	if (fLayoutData->fLayout)
4529 		fLayoutData->fLayout->AddView(child);
4530 }
4531 
4532 
4533 bool
4534 BView::AddChild(BLayoutItem* child)
4535 {
4536 	if (!fLayoutData->fLayout)
4537 		return false;
4538 	return fLayoutData->fLayout->AddItem(child);
4539 }
4540 
4541 
4542 bool
4543 BView::_AddChild(BView* child, BView* before)
4544 {
4545 	if (!child)
4546 		return false;
4547 
4548 	if (child->fParent != NULL) {
4549 		debugger("AddChild failed - the view already has a parent.");
4550 		return false;
4551 	}
4552 
4553 	if (child == this) {
4554 		debugger("AddChild failed - cannot add a view to itself.");
4555 		return false;
4556 	}
4557 
4558 	bool lockedOwner = false;
4559 	if (fOwner && !fOwner->IsLocked()) {
4560 		fOwner->Lock();
4561 		lockedOwner = true;
4562 	}
4563 
4564 	if (!_AddChildToList(child, before)) {
4565 		debugger("AddChild failed!");
4566 		if (lockedOwner)
4567 			fOwner->Unlock();
4568 		return false;
4569 	}
4570 
4571 	if (fOwner) {
4572 		_CheckLockAndSwitchCurrent();
4573 
4574 		child->_SetOwner(fOwner);
4575 		child->_CreateSelf();
4576 		child->_Attach();
4577 
4578 		if (lockedOwner)
4579 			fOwner->Unlock();
4580 	}
4581 
4582 	InvalidateLayout();
4583 
4584 	return true;
4585 }
4586 
4587 
4588 bool
4589 BView::RemoveChild(BView* child)
4590 {
4591 	STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name()));
4592 
4593 	if (!child)
4594 		return false;
4595 
4596 	if (child->fParent != this)
4597 		return false;
4598 
4599 	return child->RemoveSelf();
4600 }
4601 
4602 
4603 int32
4604 BView::CountChildren() const
4605 {
4606 	_CheckLock();
4607 
4608 	uint32 count = 0;
4609 	BView* child = fFirstChild;
4610 
4611 	while (child != NULL) {
4612 		count++;
4613 		child = child->fNextSibling;
4614 	}
4615 
4616 	return count;
4617 }
4618 
4619 
4620 BView*
4621 BView::ChildAt(int32 index) const
4622 {
4623 	_CheckLock();
4624 
4625 	BView* child = fFirstChild;
4626 	while (child != NULL && index-- > 0) {
4627 		child = child->fNextSibling;
4628 	}
4629 
4630 	return child;
4631 }
4632 
4633 
4634 BView*
4635 BView::NextSibling() const
4636 {
4637 	return fNextSibling;
4638 }
4639 
4640 
4641 BView*
4642 BView::PreviousSibling() const
4643 {
4644 	return fPreviousSibling;
4645 }
4646 
4647 
4648 bool
4649 BView::RemoveSelf()
4650 {
4651 	_RemoveLayoutItemsFromLayout(false);
4652 
4653 	return _RemoveSelf();
4654 }
4655 
4656 
4657 bool
4658 BView::_RemoveSelf()
4659 {
4660 	STRACE(("BView(%s)::_RemoveSelf()\n", Name()));
4661 
4662 	// Remove this child from its parent
4663 
4664 	BWindow* owner = fOwner;
4665 	_CheckLock();
4666 
4667 	if (owner != NULL) {
4668 		_UpdateStateForRemove();
4669 		_Detach();
4670 	}
4671 
4672 	BView* parent = fParent;
4673 	if (!parent || !parent->_RemoveChildFromList(this))
4674 		return false;
4675 
4676 	if (owner != NULL && !fTopLevelView) {
4677 		// the top level view is deleted by the app_server automatically
4678 		owner->fLink->StartMessage(AS_VIEW_DELETE);
4679 		owner->fLink->Attach<int32>(_get_object_token_(this));
4680 	}
4681 
4682 	parent->InvalidateLayout();
4683 
4684 	STRACE(("DONE: BView(%s)::_RemoveSelf()\n", Name()));
4685 
4686 	return true;
4687 }
4688 
4689 
4690 void
4691 BView::_RemoveLayoutItemsFromLayout(bool deleteItems)
4692 {
4693 	if (fParent == NULL || fParent->fLayoutData->fLayout == NULL)
4694 		return;
4695 
4696 	int32 index = fLayoutData->fLayoutItems.CountItems();
4697 	while (index-- > 0) {
4698 		BLayoutItem* item = fLayoutData->fLayoutItems.ItemAt(index);
4699 		item->RemoveSelf();
4700 			// Removes item from fLayoutItems list
4701 		if (deleteItems)
4702 			delete item;
4703 	}
4704 }
4705 
4706 
4707 BView*
4708 BView::Parent() const
4709 {
4710 	if (fParent && fParent->fTopLevelView)
4711 		return NULL;
4712 
4713 	return fParent;
4714 }
4715 
4716 
4717 BView*
4718 BView::FindView(const char* name) const
4719 {
4720 	if (name == NULL)
4721 		return NULL;
4722 
4723 	if (Name() != NULL && !strcmp(Name(), name))
4724 		return const_cast<BView*>(this);
4725 
4726 	BView* child = fFirstChild;
4727 	while (child != NULL) {
4728 		BView* view = child->FindView(name);
4729 		if (view != NULL)
4730 			return view;
4731 
4732 		child = child->fNextSibling;
4733 	}
4734 
4735 	return NULL;
4736 }
4737 
4738 
4739 void
4740 BView::MoveBy(float deltaX, float deltaY)
4741 {
4742 	MoveTo(fParentOffset.x + roundf(deltaX), fParentOffset.y + roundf(deltaY));
4743 }
4744 
4745 
4746 void
4747 BView::MoveTo(BPoint where)
4748 {
4749 	MoveTo(where.x, where.y);
4750 }
4751 
4752 
4753 void
4754 BView::MoveTo(float x, float y)
4755 {
4756 	if (x == fParentOffset.x && y == fParentOffset.y)
4757 		return;
4758 
4759 	// BeBook says we should do this. And it makes sense.
4760 	x = roundf(x);
4761 	y = roundf(y);
4762 
4763 	if (fOwner) {
4764 		_CheckLockAndSwitchCurrent();
4765 		fOwner->fLink->StartMessage(AS_VIEW_MOVE_TO);
4766 		fOwner->fLink->Attach<float>(x);
4767 		fOwner->fLink->Attach<float>(y);
4768 
4769 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4770 
4771 		_FlushIfNotInTransaction();
4772 	}
4773 
4774 	_MoveTo((int32)x, (int32)y);
4775 }
4776 
4777 
4778 void
4779 BView::ResizeBy(float deltaWidth, float deltaHeight)
4780 {
4781 	// BeBook says we should do this. And it makes sense.
4782 	deltaWidth = roundf(deltaWidth);
4783 	deltaHeight = roundf(deltaHeight);
4784 
4785 	if (deltaWidth == 0 && deltaHeight == 0)
4786 		return;
4787 
4788 	if (fOwner) {
4789 		_CheckLockAndSwitchCurrent();
4790 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_TO);
4791 
4792 		fOwner->fLink->Attach<float>(fBounds.Width() + deltaWidth);
4793 		fOwner->fLink->Attach<float>(fBounds.Height() + deltaHeight);
4794 
4795 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4796 
4797 		_FlushIfNotInTransaction();
4798 	}
4799 
4800 	_ResizeBy((int32)deltaWidth, (int32)deltaHeight);
4801 }
4802 
4803 
4804 void
4805 BView::ResizeTo(float width, float height)
4806 {
4807 	ResizeBy(width - fBounds.Width(), height - fBounds.Height());
4808 }
4809 
4810 
4811 void
4812 BView::ResizeTo(BSize size)
4813 {
4814 	ResizeBy(size.width - fBounds.Width(), size.height - fBounds.Height());
4815 }
4816 
4817 
4818 //	#pragma mark - Inherited Methods (from BHandler)
4819 
4820 
4821 status_t
4822 BView::GetSupportedSuites(BMessage* data)
4823 {
4824 	if (data == NULL)
4825 		return B_BAD_VALUE;
4826 
4827 	status_t status = data->AddString("suites", "suite/vnd.Be-view");
4828 	BPropertyInfo propertyInfo(sViewPropInfo);
4829 	if (status == B_OK)
4830 		status = data->AddFlat("messages", &propertyInfo);
4831 	if (status == B_OK)
4832 		return BHandler::GetSupportedSuites(data);
4833 	return status;
4834 }
4835 
4836 
4837 BHandler*
4838 BView::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
4839 	int32 what, const char* property)
4840 {
4841 	if (message->what == B_WINDOW_MOVE_BY
4842 		|| message->what == B_WINDOW_MOVE_TO) {
4843 		return this;
4844 	}
4845 
4846 	BPropertyInfo propertyInfo(sViewPropInfo);
4847 	status_t err = B_BAD_SCRIPT_SYNTAX;
4848 	BMessage replyMsg(B_REPLY);
4849 
4850 	switch (propertyInfo.FindMatch(message, index, specifier, what, property)) {
4851 		case 0:
4852 		case 1:
4853 		case 3:
4854 			return this;
4855 
4856 		case 2:
4857 			if (fShelf) {
4858 				message->PopSpecifier();
4859 				return fShelf;
4860 			}
4861 
4862 			err = B_NAME_NOT_FOUND;
4863 			replyMsg.AddString("message", "This window doesn't have a shelf");
4864 			break;
4865 
4866 		case 4:
4867 		{
4868 			if (!fFirstChild) {
4869 				err = B_NAME_NOT_FOUND;
4870 				replyMsg.AddString("message", "This window doesn't have "
4871 					"children.");
4872 				break;
4873 			}
4874 			BView* child = NULL;
4875 			switch (what) {
4876 				case B_INDEX_SPECIFIER:
4877 				{
4878 					int32 index;
4879 					err = specifier->FindInt32("index", &index);
4880 					if (err == B_OK)
4881 						child = ChildAt(index);
4882 					break;
4883 				}
4884 				case B_REVERSE_INDEX_SPECIFIER:
4885 				{
4886 					int32 rindex;
4887 					err = specifier->FindInt32("index", &rindex);
4888 					if (err == B_OK)
4889 						child = ChildAt(CountChildren() - rindex);
4890 					break;
4891 				}
4892 				case B_NAME_SPECIFIER:
4893 				{
4894 					const char* name;
4895 					err = specifier->FindString("name", &name);
4896 					if (err == B_OK)
4897 						child = FindView(name);
4898 					break;
4899 				}
4900 			}
4901 
4902 			if (child != NULL) {
4903 				message->PopSpecifier();
4904 				return child;
4905 			}
4906 
4907 			if (err == B_OK)
4908 				err = B_BAD_INDEX;
4909 
4910 			replyMsg.AddString("message",
4911 				"Cannot find view at/with specified index/name.");
4912 			break;
4913 		}
4914 
4915 		default:
4916 			return BHandler::ResolveSpecifier(message, index, specifier, what,
4917 				property);
4918 	}
4919 
4920 	if (err < B_OK) {
4921 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
4922 
4923 		if (err == B_BAD_SCRIPT_SYNTAX)
4924 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
4925 		else
4926 			replyMsg.AddString("message", strerror(err));
4927 	}
4928 
4929 	replyMsg.AddInt32("error", err);
4930 	message->SendReply(&replyMsg);
4931 	return NULL;
4932 }
4933 
4934 
4935 void
4936 BView::MessageReceived(BMessage* message)
4937 {
4938 	if (!message->HasSpecifiers()) {
4939 		switch (message->what) {
4940 			case B_INVALIDATE:
4941 			{
4942 				BRect rect;
4943 				if (message->FindRect("be:area", &rect) == B_OK)
4944 					Invalidate(rect);
4945 				else
4946 					Invalidate();
4947 				break;
4948 			}
4949 
4950 			case B_KEY_DOWN:
4951 			{
4952 				// TODO: cannot use "string" here if we support having different
4953 				// font encoding per view (it's supposed to be converted by
4954 				// BWindow::_HandleKeyDown() one day)
4955 				const char* string;
4956 				ssize_t bytes;
4957 				if (message->FindData("bytes", B_STRING_TYPE,
4958 						(const void**)&string, &bytes) == B_OK)
4959 					KeyDown(string, bytes - 1);
4960 				break;
4961 			}
4962 
4963 			case B_KEY_UP:
4964 			{
4965 				// TODO: same as above
4966 				const char* string;
4967 				ssize_t bytes;
4968 				if (message->FindData("bytes", B_STRING_TYPE,
4969 						(const void**)&string, &bytes) == B_OK)
4970 					KeyUp(string, bytes - 1);
4971 				break;
4972 			}
4973 
4974 			case B_VIEW_RESIZED:
4975 				FrameResized(message->GetInt32("width", 0),
4976 					message->GetInt32("height", 0));
4977 				break;
4978 
4979 			case B_VIEW_MOVED:
4980 				FrameMoved(fParentOffset);
4981 				break;
4982 
4983 			case B_MOUSE_DOWN:
4984 			{
4985 				BPoint where;
4986 				message->FindPoint("be:view_where", &where);
4987 				MouseDown(where);
4988 				break;
4989 			}
4990 
4991 			case B_MOUSE_IDLE:
4992 			{
4993 				BPoint where;
4994 				if (message->FindPoint("be:view_where", &where) != B_OK)
4995 					break;
4996 
4997 				BToolTip* tip;
4998 				if (GetToolTipAt(where, &tip))
4999 					ShowToolTip(tip);
5000 				else
5001 					BHandler::MessageReceived(message);
5002 				break;
5003 			}
5004 
5005 			case B_MOUSE_MOVED:
5006 			{
5007 				uint32 eventOptions = fEventOptions | fMouseEventOptions;
5008 				bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
5009 				bool dropIfLate = !(eventOptions & B_FULL_POINTER_HISTORY);
5010 
5011 				bigtime_t eventTime;
5012 				if (message->FindInt64("when", (int64*)&eventTime) < B_OK)
5013 					eventTime = system_time();
5014 
5015 				uint32 transit;
5016 				message->FindInt32("be:transit", (int32*)&transit);
5017 				// don't drop late messages with these important transit values
5018 				if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
5019 					dropIfLate = false;
5020 
5021 				// TODO: The dropping code may have the following problem: On
5022 				// slower computers, 20ms may just be to abitious a delay.
5023 				// There, we might constantly check the message queue for a
5024 				// newer message, not find any, and still use the only but later
5025 				// than 20ms message, which of course makes the whole thing
5026 				// later than need be. An adaptive delay would be kind of neat,
5027 				// but would probably use additional BWindow members to count
5028 				// the successful versus fruitless queue searches and the delay
5029 				// value itself or something similar.
5030 				if (noHistory
5031 					|| (dropIfLate && (system_time() - eventTime > 20000))) {
5032 					// filter out older mouse moved messages in the queue
5033 					BWindow* window = Window();
5034 					window->_DequeueAll();
5035 					BMessageQueue* queue = window->MessageQueue();
5036 					queue->Lock();
5037 
5038 					BMessage* moved;
5039 					for (int32 i = 0; (moved = queue->FindMessage(i)) != NULL;
5040 						 i++) {
5041 						if (moved != message && moved->what == B_MOUSE_MOVED) {
5042 							// there is a newer mouse moved message in the
5043 							// queue, just ignore the current one, the newer one
5044 							// will be handled here eventually
5045 							queue->Unlock();
5046 							return;
5047 						}
5048 					}
5049 					queue->Unlock();
5050 				}
5051 
5052 				BPoint where;
5053 				uint32 buttons;
5054 				message->FindPoint("be:view_where", &where);
5055 				message->FindInt32("buttons", (int32*)&buttons);
5056 
5057 				if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)
5058 					HideToolTip();
5059 
5060 				BMessage* dragMessage = NULL;
5061 				if (message->HasMessage("be:drag_message")) {
5062 					dragMessage = new BMessage();
5063 					if (message->FindMessage("be:drag_message", dragMessage)
5064 						!= B_OK) {
5065 						delete dragMessage;
5066 						dragMessage = NULL;
5067 					}
5068 				}
5069 
5070 				MouseMoved(where, transit, dragMessage);
5071 				delete dragMessage;
5072 				break;
5073 			}
5074 
5075 			case B_MOUSE_UP:
5076 			{
5077 				BPoint where;
5078 				message->FindPoint("be:view_where", &where);
5079 				fMouseEventOptions = 0;
5080 				MouseUp(where);
5081 				break;
5082 			}
5083 
5084 			case B_MOUSE_WHEEL_CHANGED:
5085 			{
5086 				BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
5087 				BScrollBar* vertical = ScrollBar(B_VERTICAL);
5088 				if (horizontal == NULL && vertical == NULL) {
5089 					// Pass the message to the next handler
5090 					BHandler::MessageReceived(message);
5091 					break;
5092 				}
5093 
5094 				float deltaX = 0.0f;
5095 				float deltaY = 0.0f;
5096 
5097 				if (horizontal != NULL)
5098 					message->FindFloat("be:wheel_delta_x", &deltaX);
5099 
5100 				if (vertical != NULL)
5101 					message->FindFloat("be:wheel_delta_y", &deltaY);
5102 
5103 				if (deltaX == 0.0f && deltaY == 0.0f)
5104 					break;
5105 
5106 				if ((modifiers() & B_CONTROL_KEY) != 0)
5107 					std::swap(horizontal, vertical);
5108 
5109 				if (horizontal != NULL && deltaX != 0.0f)
5110 					ScrollWithMouseWheelDelta(horizontal, deltaX);
5111 
5112 				if (vertical != NULL && deltaY != 0.0f)
5113 					ScrollWithMouseWheelDelta(vertical, deltaY);
5114 
5115 				break;
5116 			}
5117 
5118 			// prevent message repeats
5119 			case B_COLORS_UPDATED:
5120 			case B_FONTS_UPDATED:
5121 				break;
5122 
5123 			case B_SCREEN_CHANGED:
5124 			{
5125 				// propegate message to child views
5126 				int32 childCount = CountChildren();
5127 				for (int32 i = 0; i < childCount; i++) {
5128 					BView* view = ChildAt(i);
5129 					if (view != NULL)
5130 						view->MessageReceived(message);
5131 				}
5132 				break;
5133 			}
5134 
5135 			default:
5136 				BHandler::MessageReceived(message);
5137 				break;
5138 		}
5139 
5140 		return;
5141 	}
5142 
5143 	// Scripting message
5144 
5145 	BMessage replyMsg(B_REPLY);
5146 	status_t err = B_BAD_SCRIPT_SYNTAX;
5147 	int32 index;
5148 	BMessage specifier;
5149 	int32 what;
5150 	const char* property;
5151 
5152 	if (message->GetCurrentSpecifier(&index, &specifier, &what, &property)
5153 			!= B_OK) {
5154 		return BHandler::MessageReceived(message);
5155 	}
5156 
5157 	BPropertyInfo propertyInfo(sViewPropInfo);
5158 	switch (propertyInfo.FindMatch(message, index, &specifier, what,
5159 			property)) {
5160 		case 0:
5161 			if (message->what == B_GET_PROPERTY) {
5162 				err = replyMsg.AddRect("result", Frame());
5163 			} else if (message->what == B_SET_PROPERTY) {
5164 				BRect newFrame;
5165 				err = message->FindRect("data", &newFrame);
5166 				if (err == B_OK) {
5167 					MoveTo(newFrame.LeftTop());
5168 					ResizeTo(newFrame.Width(), newFrame.Height());
5169 				}
5170 			}
5171 			break;
5172 		case 1:
5173 			if (message->what == B_GET_PROPERTY) {
5174 				err = replyMsg.AddBool("result", IsHidden());
5175 			} else if (message->what == B_SET_PROPERTY) {
5176 				bool newHiddenState;
5177 				err = message->FindBool("data", &newHiddenState);
5178 				if (err == B_OK) {
5179 					if (newHiddenState == true)
5180 						Hide();
5181 					else
5182 						Show();
5183 				}
5184 			}
5185 			break;
5186 		case 3:
5187 			err = replyMsg.AddInt32("result", CountChildren());
5188 			break;
5189 		default:
5190 			return BHandler::MessageReceived(message);
5191 	}
5192 
5193 	if (err != B_OK) {
5194 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
5195 
5196 		if (err == B_BAD_SCRIPT_SYNTAX)
5197 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
5198 		else
5199 			replyMsg.AddString("message", strerror(err));
5200 
5201 		replyMsg.AddInt32("error", err);
5202 	}
5203 
5204 	message->SendReply(&replyMsg);
5205 }
5206 
5207 
5208 status_t
5209 BView::Perform(perform_code code, void* _data)
5210 {
5211 	switch (code) {
5212 		case PERFORM_CODE_MIN_SIZE:
5213 			((perform_data_min_size*)_data)->return_value
5214 				= BView::MinSize();
5215 			return B_OK;
5216 		case PERFORM_CODE_MAX_SIZE:
5217 			((perform_data_max_size*)_data)->return_value
5218 				= BView::MaxSize();
5219 			return B_OK;
5220 		case PERFORM_CODE_PREFERRED_SIZE:
5221 			((perform_data_preferred_size*)_data)->return_value
5222 				= BView::PreferredSize();
5223 			return B_OK;
5224 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
5225 			((perform_data_layout_alignment*)_data)->return_value
5226 				= BView::LayoutAlignment();
5227 			return B_OK;
5228 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
5229 			((perform_data_has_height_for_width*)_data)->return_value
5230 				= BView::HasHeightForWidth();
5231 			return B_OK;
5232 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
5233 		{
5234 			perform_data_get_height_for_width* data
5235 				= (perform_data_get_height_for_width*)_data;
5236 			BView::GetHeightForWidth(data->width, &data->min, &data->max,
5237 				&data->preferred);
5238 			return B_OK;
5239 		}
5240 		case PERFORM_CODE_SET_LAYOUT:
5241 		{
5242 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
5243 			BView::SetLayout(data->layout);
5244 			return B_OK;
5245 		}
5246 		case PERFORM_CODE_LAYOUT_INVALIDATED:
5247 		{
5248 			perform_data_layout_invalidated* data
5249 				= (perform_data_layout_invalidated*)_data;
5250 			BView::LayoutInvalidated(data->descendants);
5251 			return B_OK;
5252 		}
5253 		case PERFORM_CODE_DO_LAYOUT:
5254 		{
5255 			BView::DoLayout();
5256 			return B_OK;
5257 		}
5258 		case PERFORM_CODE_LAYOUT_CHANGED:
5259 		{
5260 			BView::LayoutChanged();
5261 			return B_OK;
5262 		}
5263 		case PERFORM_CODE_GET_TOOL_TIP_AT:
5264 		{
5265 			perform_data_get_tool_tip_at* data
5266 				= (perform_data_get_tool_tip_at*)_data;
5267 			data->return_value
5268 				= BView::GetToolTipAt(data->point, data->tool_tip);
5269 			return B_OK;
5270 		}
5271 		case PERFORM_CODE_ALL_UNARCHIVED:
5272 		{
5273 			perform_data_all_unarchived* data =
5274 				(perform_data_all_unarchived*)_data;
5275 
5276 			data->return_value = BView::AllUnarchived(data->archive);
5277 			return B_OK;
5278 		}
5279 		case PERFORM_CODE_ALL_ARCHIVED:
5280 		{
5281 			perform_data_all_archived* data =
5282 				(perform_data_all_archived*)_data;
5283 
5284 			data->return_value = BView::AllArchived(data->archive);
5285 			return B_OK;
5286 		}
5287 	}
5288 
5289 	return BHandler::Perform(code, _data);
5290 }
5291 
5292 
5293 // #pragma mark - Layout Functions
5294 
5295 
5296 BSize
5297 BView::MinSize()
5298 {
5299 	// TODO: make sure this works correctly when some methods are overridden
5300 	float width, height;
5301 	GetPreferredSize(&width, &height);
5302 
5303 	return BLayoutUtils::ComposeSize(fLayoutData->fMinSize,
5304 		(fLayoutData->fLayout ? fLayoutData->fLayout->MinSize()
5305 			: BSize(width, height)));
5306 }
5307 
5308 
5309 BSize
5310 BView::MaxSize()
5311 {
5312 	return BLayoutUtils::ComposeSize(fLayoutData->fMaxSize,
5313 		(fLayoutData->fLayout ? fLayoutData->fLayout->MaxSize()
5314 			: BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)));
5315 }
5316 
5317 
5318 BSize
5319 BView::PreferredSize()
5320 {
5321 	// TODO: make sure this works correctly when some methods are overridden
5322 	float width, height;
5323 	GetPreferredSize(&width, &height);
5324 
5325 	return BLayoutUtils::ComposeSize(fLayoutData->fPreferredSize,
5326 		(fLayoutData->fLayout ? fLayoutData->fLayout->PreferredSize()
5327 			: BSize(width, height)));
5328 }
5329 
5330 
5331 BAlignment
5332 BView::LayoutAlignment()
5333 {
5334 	return BLayoutUtils::ComposeAlignment(fLayoutData->fAlignment,
5335 		(fLayoutData->fLayout ? fLayoutData->fLayout->Alignment()
5336 			: BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER)));
5337 }
5338 
5339 
5340 void
5341 BView::SetExplicitMinSize(BSize size)
5342 {
5343 	fLayoutData->fMinSize = size;
5344 	InvalidateLayout();
5345 }
5346 
5347 
5348 void
5349 BView::SetExplicitMaxSize(BSize size)
5350 {
5351 	fLayoutData->fMaxSize = size;
5352 	InvalidateLayout();
5353 }
5354 
5355 
5356 void
5357 BView::SetExplicitPreferredSize(BSize size)
5358 {
5359 	fLayoutData->fPreferredSize = size;
5360 	InvalidateLayout();
5361 }
5362 
5363 
5364 void
5365 BView::SetExplicitSize(BSize size)
5366 {
5367 	fLayoutData->fMinSize = size;
5368 	fLayoutData->fMaxSize = size;
5369 	fLayoutData->fPreferredSize = size;
5370 	InvalidateLayout();
5371 }
5372 
5373 
5374 void
5375 BView::SetExplicitAlignment(BAlignment alignment)
5376 {
5377 	fLayoutData->fAlignment = alignment;
5378 	InvalidateLayout();
5379 }
5380 
5381 
5382 BSize
5383 BView::ExplicitMinSize() const
5384 {
5385 	return fLayoutData->fMinSize;
5386 }
5387 
5388 
5389 BSize
5390 BView::ExplicitMaxSize() const
5391 {
5392 	return fLayoutData->fMaxSize;
5393 }
5394 
5395 
5396 BSize
5397 BView::ExplicitPreferredSize() const
5398 {
5399 	return fLayoutData->fPreferredSize;
5400 }
5401 
5402 
5403 BAlignment
5404 BView::ExplicitAlignment() const
5405 {
5406 	return fLayoutData->fAlignment;
5407 }
5408 
5409 
5410 bool
5411 BView::HasHeightForWidth()
5412 {
5413 	return (fLayoutData->fLayout
5414 		? fLayoutData->fLayout->HasHeightForWidth() : false);
5415 }
5416 
5417 
5418 void
5419 BView::GetHeightForWidth(float width, float* min, float* max, float* preferred)
5420 {
5421 	if (fLayoutData->fLayout)
5422 		fLayoutData->fLayout->GetHeightForWidth(width, min, max, preferred);
5423 }
5424 
5425 
5426 void
5427 BView::SetLayout(BLayout* layout)
5428 {
5429 	if (layout == fLayoutData->fLayout)
5430 		return;
5431 
5432 	if (layout && layout->Layout())
5433 		debugger("BView::SetLayout() failed, layout is already in use.");
5434 
5435 	fFlags |= B_SUPPORTS_LAYOUT;
5436 
5437 	// unset and delete the old layout
5438 	if (fLayoutData->fLayout) {
5439 		fLayoutData->fLayout->RemoveSelf();
5440 		fLayoutData->fLayout->SetOwner(NULL);
5441 		delete fLayoutData->fLayout;
5442 	}
5443 
5444 	fLayoutData->fLayout = layout;
5445 
5446 	if (fLayoutData->fLayout) {
5447 		fLayoutData->fLayout->SetOwner(this);
5448 
5449 		// add all children
5450 		int count = CountChildren();
5451 		for (int i = 0; i < count; i++)
5452 			fLayoutData->fLayout->AddView(ChildAt(i));
5453 	}
5454 
5455 	InvalidateLayout();
5456 }
5457 
5458 
5459 BLayout*
5460 BView::GetLayout() const
5461 {
5462 	return fLayoutData->fLayout;
5463 }
5464 
5465 
5466 void
5467 BView::InvalidateLayout(bool descendants)
5468 {
5469 	// printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
5470 	//	this, descendants, fLayoutData->fLayoutValid,
5471 	//	fLayoutData->fLayoutInProgress);
5472 
5473 	if (!fLayoutData->fMinMaxValid || fLayoutData->fLayoutInProgress
5474  			|| fLayoutData->fLayoutInvalidationDisabled > 0) {
5475 		return;
5476 	}
5477 	fLayoutData->fLayoutValid = false;
5478 	fLayoutData->fMinMaxValid = false;
5479 	LayoutInvalidated(descendants);
5480 
5481 	if (descendants) {
5482 		for (BView* child = fFirstChild;
5483 			child; child = child->fNextSibling) {
5484 			child->InvalidateLayout(descendants);
5485 		}
5486 	}
5487 
5488 	if (fLayoutData->fLayout)
5489 		fLayoutData->fLayout->InvalidateLayout(descendants);
5490 	else
5491 		_InvalidateParentLayout();
5492 
5493 	if (fTopLevelView
5494 		&& fOwner != NULL)
5495 		fOwner->PostMessage(B_LAYOUT_WINDOW);
5496 }
5497 
5498 
5499 void
5500 BView::EnableLayoutInvalidation()
5501 {
5502 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5503 		fLayoutData->fLayoutInvalidationDisabled--;
5504 }
5505 
5506 
5507 void
5508 BView::DisableLayoutInvalidation()
5509 {
5510 	fLayoutData->fLayoutInvalidationDisabled++;
5511 }
5512 
5513 
5514 bool
5515 BView::IsLayoutInvalidationDisabled()
5516 {
5517 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5518 		return true;
5519 	return false;
5520 }
5521 
5522 
5523 bool
5524 BView::IsLayoutValid() const
5525 {
5526 	return fLayoutData->fLayoutValid;
5527 }
5528 
5529 
5530 void
5531 BView::ResetLayoutInvalidation()
5532 {
5533 	fLayoutData->fMinMaxValid = true;
5534 }
5535 
5536 
5537 BLayoutContext*
5538 BView::LayoutContext() const
5539 {
5540 	return fLayoutData->fLayoutContext;
5541 }
5542 
5543 
5544 void
5545 BView::Layout(bool force)
5546 {
5547 	BLayoutContext context;
5548 	_Layout(force, &context);
5549 }
5550 
5551 
5552 void
5553 BView::Relayout()
5554 {
5555 	if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) {
5556 		fLayoutData->fNeedsRelayout = true;
5557 		if (fLayoutData->fLayout)
5558 			fLayoutData->fLayout->RequireLayout();
5559 
5560 		// Layout() is recursive, that is if the parent view is currently laid
5561 		// out, we don't call layout() on this view, but wait for the parent's
5562 		// Layout() to do that for us.
5563 		if (!fParent || !fParent->fLayoutData->fLayoutInProgress)
5564 			Layout(false);
5565 	}
5566 }
5567 
5568 
5569 void
5570 BView::LayoutInvalidated(bool descendants)
5571 {
5572 	// hook method
5573 }
5574 
5575 
5576 void
5577 BView::DoLayout()
5578 {
5579 	if (fLayoutData->fLayout)
5580 		fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
5581 }
5582 
5583 
5584 void
5585 BView::SetToolTip(const char* text)
5586 {
5587 	if (text == NULL || text[0] == '\0') {
5588 		SetToolTip((BToolTip*)NULL);
5589 		return;
5590 	}
5591 
5592 	if (BTextToolTip* tip = dynamic_cast<BTextToolTip*>(fToolTip))
5593 		tip->SetText(text);
5594 	else
5595 		SetToolTip(new BTextToolTip(text));
5596 }
5597 
5598 
5599 void
5600 BView::SetToolTip(BToolTip* tip)
5601 {
5602 	if (fToolTip == tip)
5603 		return;
5604 	else if (tip == NULL)
5605 		HideToolTip();
5606 
5607 	if (fToolTip != NULL)
5608 		fToolTip->ReleaseReference();
5609 
5610 	fToolTip = tip;
5611 
5612 	if (fToolTip != NULL)
5613 		fToolTip->AcquireReference();
5614 }
5615 
5616 
5617 BToolTip*
5618 BView::ToolTip() const
5619 {
5620 	return fToolTip;
5621 }
5622 
5623 
5624 void
5625 BView::ShowToolTip(BToolTip* tip)
5626 {
5627 	if (tip == NULL)
5628 		return;
5629 
5630 	BPoint where;
5631 	GetMouse(&where, NULL, false);
5632 
5633 	BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where), this);
5634 }
5635 
5636 
5637 void
5638 BView::HideToolTip()
5639 {
5640 	BToolTipManager::Manager()->HideTip();
5641 }
5642 
5643 
5644 bool
5645 BView::GetToolTipAt(BPoint point, BToolTip** _tip)
5646 {
5647 	if (fToolTip != NULL) {
5648 		*_tip = fToolTip;
5649 		return true;
5650 	}
5651 
5652 	*_tip = NULL;
5653 	return false;
5654 }
5655 
5656 
5657 void
5658 BView::LayoutChanged()
5659 {
5660 	// hook method
5661 }
5662 
5663 
5664 void
5665 BView::_Layout(bool force, BLayoutContext* context)
5666 {
5667 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context);
5668 //printf("  fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n",
5669 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid,
5670 //fLayoutData->fLayoutInProgress);
5671 	if (fLayoutData->fNeedsRelayout || !fLayoutData->fLayoutValid || force) {
5672 		fLayoutData->fLayoutValid = false;
5673 
5674 		if (fLayoutData->fLayoutInProgress)
5675 			return;
5676 
5677 		BLayoutContext* oldContext = fLayoutData->fLayoutContext;
5678 		fLayoutData->fLayoutContext = context;
5679 
5680 		fLayoutData->fLayoutInProgress = true;
5681 		DoLayout();
5682 		fLayoutData->fLayoutInProgress = false;
5683 
5684 		fLayoutData->fLayoutValid = true;
5685 		fLayoutData->fMinMaxValid = true;
5686 		fLayoutData->fNeedsRelayout = false;
5687 
5688 		// layout children
5689 		for(BView* child = fFirstChild; child; child = child->fNextSibling) {
5690 			if (!child->IsHidden(child))
5691 				child->_Layout(force, context);
5692 		}
5693 
5694 		LayoutChanged();
5695 
5696 		fLayoutData->fLayoutContext = oldContext;
5697 
5698 		// invalidate the drawn content, if requested
5699 		if (fFlags & B_INVALIDATE_AFTER_LAYOUT)
5700 			Invalidate();
5701 	}
5702 }
5703 
5704 
5705 void
5706 BView::_LayoutLeft(BLayout* deleted)
5707 {
5708 	// If our layout is added to another layout (via BLayout::AddItem())
5709 	// then we share ownership of our layout. In the event that our layout gets
5710 	// deleted by the layout it has been added to, this method is called so
5711 	// that we don't double-delete our layout.
5712 	if (fLayoutData->fLayout == deleted)
5713 		fLayoutData->fLayout = NULL;
5714 	InvalidateLayout();
5715 }
5716 
5717 
5718 void
5719 BView::_InvalidateParentLayout()
5720 {
5721 	if (!fParent)
5722 		return;
5723 
5724 	BLayout* layout = fLayoutData->fLayout;
5725 	BLayout* layoutParent = layout ? layout->Layout() : NULL;
5726 	if (layoutParent) {
5727 		layoutParent->InvalidateLayout();
5728 	} else if (fLayoutData->fLayoutItems.CountItems() > 0) {
5729 		int32 count = fLayoutData->fLayoutItems.CountItems();
5730 		for (int32 i = 0; i < count; i++) {
5731 			fLayoutData->fLayoutItems.ItemAt(i)->Layout()->InvalidateLayout();
5732 		}
5733 	} else {
5734 		fParent->InvalidateLayout();
5735 	}
5736 }
5737 
5738 
5739 //	#pragma mark - Private Functions
5740 
5741 
5742 void
5743 BView::_InitData(BRect frame, const char* name, uint32 resizingMode,
5744 	uint32 flags)
5745 {
5746 	// Info: The name of the view is set by BHandler constructor
5747 
5748 	STRACE(("BView::_InitData: enter\n"));
5749 
5750 	// initialize members
5751 	if ((resizingMode & ~_RESIZE_MASK_) || (flags & _RESIZE_MASK_))
5752 		printf("%s BView::_InitData(): resizing mode or flags swapped\n", name);
5753 
5754 	// There are applications that swap the resize mask and the flags in the
5755 	// BView constructor. This does not cause problems under BeOS as it just
5756 	// ors the two fields to one 32bit flag.
5757 	// For now we do the same but print the above warning message.
5758 	// TODO: this should be removed at some point and the original
5759 	// version restored:
5760 	// fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
5761 	fFlags = resizingMode | flags;
5762 
5763 	// handle rounding
5764 	frame.left = roundf(frame.left);
5765 	frame.top = roundf(frame.top);
5766 	frame.right = roundf(frame.right);
5767 	frame.bottom = roundf(frame.bottom);
5768 
5769 	fParentOffset.Set(frame.left, frame.top);
5770 
5771 	fOwner = NULL;
5772 	fParent = NULL;
5773 	fNextSibling = NULL;
5774 	fPreviousSibling = NULL;
5775 	fFirstChild = NULL;
5776 
5777 	fShowLevel = 0;
5778 	fTopLevelView = false;
5779 
5780 	fCurrentPicture = NULL;
5781 	fCommArray = NULL;
5782 
5783 	fVerScroller = NULL;
5784 	fHorScroller = NULL;
5785 
5786 	fIsPrinting = false;
5787 	fAttached = false;
5788 
5789 	// TODO: Since we cannot communicate failure, we don't use std::nothrow here
5790 	// TODO: Maybe we could auto-delete those views on AddChild() instead?
5791 	fState = new BPrivate::ViewState;
5792 
5793 	fBounds = frame.OffsetToCopy(B_ORIGIN);
5794 	fShelf = NULL;
5795 
5796 	fEventMask = 0;
5797 	fEventOptions = 0;
5798 	fMouseEventOptions = 0;
5799 
5800 	fLayoutData = new LayoutData;
5801 
5802 	fToolTip = NULL;
5803 
5804 	if ((flags & B_SUPPORTS_LAYOUT) != 0) {
5805 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
5806 		SetLowUIColor(ViewUIColor());
5807 		SetHighUIColor(B_PANEL_TEXT_COLOR);
5808 	}
5809 }
5810 
5811 
5812 void
5813 BView::_RemoveCommArray()
5814 {
5815 	if (fCommArray) {
5816 		delete [] fCommArray->array;
5817 		delete fCommArray;
5818 		fCommArray = NULL;
5819 	}
5820 }
5821 
5822 
5823 void
5824 BView::_SetOwner(BWindow* newOwner)
5825 {
5826 	if (!newOwner)
5827 		_RemoveCommArray();
5828 
5829 	if (fOwner != newOwner && fOwner) {
5830 		if (fOwner->fFocus == this)
5831 			MakeFocus(false);
5832 
5833 		if (fOwner->fLastMouseMovedView == this)
5834 			fOwner->fLastMouseMovedView = NULL;
5835 
5836 		fOwner->RemoveHandler(this);
5837 		if (fShelf)
5838 			fOwner->RemoveHandler(fShelf);
5839 	}
5840 
5841 	if (newOwner && newOwner != fOwner) {
5842 		newOwner->AddHandler(this);
5843 		if (fShelf)
5844 			newOwner->AddHandler(fShelf);
5845 
5846 		if (fTopLevelView)
5847 			SetNextHandler(newOwner);
5848 		else
5849 			SetNextHandler(fParent);
5850 	}
5851 
5852 	fOwner = newOwner;
5853 
5854 	for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling)
5855 		child->_SetOwner(newOwner);
5856 }
5857 
5858 
5859 void
5860 BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
5861 {
5862 	if (!_CheckOwnerLockAndSwitchCurrent())
5863 		return;
5864 
5865 	if (picture == NULL) {
5866 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5867 		fOwner->fLink->Attach<int32>(-1);
5868 
5869 		// NOTE: No need to sync here, since the -1 token cannot
5870 		// become invalid on the server.
5871 	} else {
5872 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5873 		fOwner->fLink->Attach<int32>(picture->Token());
5874 		fOwner->fLink->Attach<BPoint>(where);
5875 		fOwner->fLink->Attach<bool>(invert);
5876 
5877 		// NOTE: "sync" defaults to true in public methods. If you know what
5878 		// you are doing, i.e. if you know your BPicture stays valid, you
5879 		// can avoid the performance impact of syncing. In a use-case where
5880 		// the client creates BPictures on the stack, these BPictures may
5881 		// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
5882 		// goes out of scope, and the command is processed earlier in the
5883 		// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
5884 		// ServerWindow thread, which will then have the result that no
5885 		// ServerPicture is found of the token.
5886 		if (sync)
5887 			Sync();
5888 	}
5889 }
5890 
5891 
5892 void
5893 BView::_ClipToRect(BRect rect, bool inverse)
5894 {
5895 	if (_CheckOwnerLockAndSwitchCurrent()) {
5896 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_RECT);
5897 		fOwner->fLink->Attach<bool>(inverse);
5898 		fOwner->fLink->Attach<BRect>(rect);
5899 		_FlushIfNotInTransaction();
5900 	}
5901 }
5902 
5903 
5904 void
5905 BView::_ClipToShape(BShape* shape, bool inverse)
5906 {
5907 	if (shape == NULL)
5908 		return;
5909 
5910 	shape_data* sd = (shape_data*)shape->fPrivateData;
5911 	if (sd->opCount == 0 || sd->ptCount == 0)
5912 		return;
5913 
5914 	if (_CheckOwnerLockAndSwitchCurrent()) {
5915 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_SHAPE);
5916 		fOwner->fLink->Attach<bool>(inverse);
5917 		fOwner->fLink->Attach<int32>(sd->opCount);
5918 		fOwner->fLink->Attach<int32>(sd->ptCount);
5919 		fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32));
5920 		fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
5921 		_FlushIfNotInTransaction();
5922 	}
5923 }
5924 
5925 
5926 bool
5927 BView::_RemoveChildFromList(BView* child)
5928 {
5929 	if (child->fParent != this)
5930 		return false;
5931 
5932 	if (fFirstChild == child) {
5933 		// it's the first view in the list
5934 		fFirstChild = child->fNextSibling;
5935 	} else {
5936 		// there must be a previous sibling
5937 		child->fPreviousSibling->fNextSibling = child->fNextSibling;
5938 	}
5939 
5940 	if (child->fNextSibling)
5941 		child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
5942 
5943 	child->fParent = NULL;
5944 	child->fNextSibling = NULL;
5945 	child->fPreviousSibling = NULL;
5946 
5947 	return true;
5948 }
5949 
5950 
5951 bool
5952 BView::_AddChildToList(BView* child, BView* before)
5953 {
5954 	if (!child)
5955 		return false;
5956 	if (child->fParent != NULL) {
5957 		debugger("View already belongs to someone else");
5958 		return false;
5959 	}
5960 	if (before != NULL && before->fParent != this) {
5961 		debugger("Invalid before view");
5962 		return false;
5963 	}
5964 
5965 	if (before != NULL) {
5966 		// add view before this one
5967 		child->fNextSibling = before;
5968 		child->fPreviousSibling = before->fPreviousSibling;
5969 		if (child->fPreviousSibling != NULL)
5970 			child->fPreviousSibling->fNextSibling = child;
5971 
5972 		before->fPreviousSibling = child;
5973 		if (fFirstChild == before)
5974 			fFirstChild = child;
5975 	} else {
5976 		// add view to the end of the list
5977 		BView* last = fFirstChild;
5978 		while (last != NULL && last->fNextSibling != NULL) {
5979 			last = last->fNextSibling;
5980 		}
5981 
5982 		if (last != NULL) {
5983 			last->fNextSibling = child;
5984 			child->fPreviousSibling = last;
5985 		} else {
5986 			fFirstChild = child;
5987 			child->fPreviousSibling = NULL;
5988 		}
5989 
5990 		child->fNextSibling = NULL;
5991 	}
5992 
5993 	child->fParent = this;
5994 	return true;
5995 }
5996 
5997 
5998 /*!	\brief Creates the server counterpart of this view.
5999 	This is only done for views that are part of the view hierarchy, ie. when
6000 	they are attached to a window.
6001 	RemoveSelf() deletes the server object again.
6002 */
6003 bool
6004 BView::_CreateSelf()
6005 {
6006 	// AS_VIEW_CREATE & AS_VIEW_CREATE_ROOT do not use the
6007 	// current view mechanism via _CheckLockAndSwitchCurrent() - the token
6008 	// of the view and its parent are both send to the server.
6009 
6010 	if (fTopLevelView)
6011 		fOwner->fLink->StartMessage(AS_VIEW_CREATE_ROOT);
6012 	else
6013  		fOwner->fLink->StartMessage(AS_VIEW_CREATE);
6014 
6015 	fOwner->fLink->Attach<int32>(_get_object_token_(this));
6016 	fOwner->fLink->AttachString(Name());
6017 	fOwner->fLink->Attach<BRect>(Frame());
6018 	fOwner->fLink->Attach<BPoint>(LeftTop());
6019 	fOwner->fLink->Attach<uint32>(ResizingMode());
6020 	fOwner->fLink->Attach<uint32>(fEventMask);
6021 	fOwner->fLink->Attach<uint32>(fEventOptions);
6022 	fOwner->fLink->Attach<uint32>(Flags());
6023 	fOwner->fLink->Attach<bool>(IsHidden(this));
6024 	fOwner->fLink->Attach<rgb_color>(fState->view_color);
6025 	if (fTopLevelView)
6026 		fOwner->fLink->Attach<int32>(B_NULL_TOKEN);
6027 	else
6028 		fOwner->fLink->Attach<int32>(_get_object_token_(fParent));
6029 	fOwner->fLink->Flush();
6030 
6031 	_CheckOwnerLockAndSwitchCurrent();
6032 	fState->UpdateServerState(*fOwner->fLink);
6033 
6034 	// we create all its children, too
6035 
6036 	for (BView* child = fFirstChild; child != NULL;
6037 			child = child->fNextSibling) {
6038 		child->_CreateSelf();
6039 	}
6040 
6041 	fOwner->fLink->Flush();
6042 	return true;
6043 }
6044 
6045 
6046 /*!	Sets the new view position.
6047 	It doesn't contact the server, though - the only case where this
6048 	is called outside of MoveTo() is as reaction of moving a view
6049 	in the server (a.k.a. B_WINDOW_RESIZED).
6050 	It also calls the BView's FrameMoved() hook.
6051 */
6052 void
6053 BView::_MoveTo(int32 x, int32 y)
6054 {
6055 	fParentOffset.Set(x, y);
6056 
6057 	if (Window() != NULL && fFlags & B_FRAME_EVENTS) {
6058 		BMessage moved(B_VIEW_MOVED);
6059 		moved.AddInt64("when", system_time());
6060 		moved.AddPoint("where", BPoint(x, y));
6061 
6062 		BMessenger target(this);
6063 		target.SendMessage(&moved);
6064 	}
6065 }
6066 
6067 
6068 /*!	Computes the actual new frame size and recalculates the size of
6069 	the children as well.
6070 	It doesn't contact the server, though - the only case where this
6071 	is called outside of ResizeBy() is as reaction of resizing a view
6072 	in the server (a.k.a. B_WINDOW_RESIZED).
6073 	It also calls the BView's FrameResized() hook.
6074 */
6075 void
6076 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight)
6077 {
6078 	fBounds.right += deltaWidth;
6079 	fBounds.bottom += deltaHeight;
6080 
6081 	if (Window() == NULL) {
6082 		// we're not supposed to exercise the resizing code in case
6083 		// we haven't been attached to a window yet
6084 		return;
6085 	}
6086 
6087 	// layout the children
6088 	if ((fFlags & B_SUPPORTS_LAYOUT) != 0) {
6089 		Relayout();
6090 	} else {
6091 		for (BView* child = fFirstChild; child; child = child->fNextSibling)
6092 			child->_ParentResizedBy(deltaWidth, deltaHeight);
6093 	}
6094 
6095 	if (fFlags & B_FRAME_EVENTS) {
6096 		BMessage resized(B_VIEW_RESIZED);
6097 		resized.AddInt64("when", system_time());
6098 		resized.AddInt32("width", fBounds.IntegerWidth());
6099 		resized.AddInt32("height", fBounds.IntegerHeight());
6100 
6101 		BMessenger target(this);
6102 		target.SendMessage(&resized);
6103 	}
6104 }
6105 
6106 
6107 /*!	Relayouts the view according to its resizing mode. */
6108 void
6109 BView::_ParentResizedBy(int32 x, int32 y)
6110 {
6111 	uint32 resizingMode = fFlags & _RESIZE_MASK_;
6112 	BRect newFrame = Frame();
6113 
6114 	// follow with left side
6115 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
6116 		newFrame.left += x;
6117 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
6118 		newFrame.left += x / 2;
6119 
6120 	// follow with right side
6121 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
6122 		newFrame.right += x;
6123 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
6124 		newFrame.right += x / 2;
6125 
6126 	// follow with top side
6127 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
6128 		newFrame.top += y;
6129 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
6130 		newFrame.top += y / 2;
6131 
6132 	// follow with bottom side
6133 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
6134 		newFrame.bottom += y;
6135 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
6136 		newFrame.bottom += y / 2;
6137 
6138 	if (newFrame.LeftTop() != fParentOffset) {
6139 		// move view
6140 		_MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top));
6141 	}
6142 
6143 	if (newFrame != Frame()) {
6144 		// resize view
6145 		int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width());
6146 		int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height());
6147 		_ResizeBy(widthDiff, heightDiff);
6148 	}
6149 }
6150 
6151 
6152 void
6153 BView::_Activate(bool active)
6154 {
6155 	WindowActivated(active);
6156 
6157 	for (BView* child = fFirstChild; child != NULL;
6158 			child = child->fNextSibling) {
6159 		child->_Activate(active);
6160 	}
6161 }
6162 
6163 
6164 void
6165 BView::_Attach()
6166 {
6167 	if (fOwner != NULL) {
6168 		// unmask state flags to force [re]syncing with the app_server
6169 		fState->valid_flags &= ~(B_VIEW_WHICH_VIEW_COLOR_BIT
6170 			| B_VIEW_WHICH_LOW_COLOR_BIT | B_VIEW_WHICH_HIGH_COLOR_BIT);
6171 
6172 		if (fState->which_view_color != B_NO_COLOR)
6173 			SetViewUIColor(fState->which_view_color,
6174 				fState->which_view_color_tint);
6175 
6176 		if (fState->which_high_color != B_NO_COLOR)
6177 			SetHighUIColor(fState->which_high_color,
6178 				fState->which_high_color_tint);
6179 
6180 		if (fState->which_low_color != B_NO_COLOR)
6181 			SetLowUIColor(fState->which_low_color,
6182 				fState->which_low_color_tint);
6183 	}
6184 
6185 	AttachedToWindow();
6186 
6187 	fAttached = true;
6188 
6189 	// after giving the view a chance to do this itself,
6190 	// check for the B_PULSE_NEEDED flag and make sure the
6191 	// window set's up the pulse messaging
6192 	if (fOwner) {
6193 		if (fFlags & B_PULSE_NEEDED) {
6194 			_CheckLock();
6195 			if (fOwner->fPulseRunner == NULL)
6196 				fOwner->SetPulseRate(fOwner->PulseRate());
6197 		}
6198 
6199 		if (!fOwner->IsHidden())
6200 			Invalidate();
6201 	}
6202 
6203 	for (BView* child = fFirstChild; child != NULL;
6204 			child = child->fNextSibling) {
6205 		// we need to check for fAttached as new views could have been
6206 		// added in AttachedToWindow() - and those are already attached
6207 		if (!child->fAttached)
6208 			child->_Attach();
6209 	}
6210 
6211 	AllAttached();
6212 }
6213 
6214 
6215 void
6216 BView::_ColorsUpdated(BMessage* message)
6217 {
6218 	if (fTopLevelView
6219 		&& fLayoutData->fLayout != NULL
6220 		&& !fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)) {
6221 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
6222 		SetHighUIColor(B_PANEL_TEXT_COLOR);
6223 	}
6224 
6225 	rgb_color color;
6226 
6227 	const char* colorName = ui_color_name(fState->which_view_color);
6228 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6229 		fState->view_color = tint_color(color, fState->which_view_color_tint);
6230 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
6231 	}
6232 
6233 	colorName = ui_color_name(fState->which_low_color);
6234 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6235 		fState->low_color = tint_color(color, fState->which_low_color_tint);
6236 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
6237 	}
6238 
6239 	colorName = ui_color_name(fState->which_high_color);
6240 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6241 		fState->high_color = tint_color(color, fState->which_high_color_tint);
6242 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
6243 	}
6244 
6245 	MessageReceived(message);
6246 
6247 	for (BView* child = fFirstChild; child != NULL;
6248 			child = child->fNextSibling)
6249 		child->_ColorsUpdated(message);
6250 
6251 	Invalidate();
6252 }
6253 
6254 
6255 void
6256 BView::_Detach()
6257 {
6258 	DetachedFromWindow();
6259 	fAttached = false;
6260 
6261 	for (BView* child = fFirstChild; child != NULL;
6262 			child = child->fNextSibling) {
6263 		child->_Detach();
6264 	}
6265 
6266 	AllDetached();
6267 
6268 	if (fOwner) {
6269 		_CheckLock();
6270 
6271 		if (!fOwner->IsHidden())
6272 			Invalidate();
6273 
6274 		// make sure our owner doesn't need us anymore
6275 
6276 		if (fOwner->CurrentFocus() == this) {
6277 			MakeFocus(false);
6278 			// MakeFocus() is virtual and might not be
6279 			// passing through to the BView version,
6280 			// but we need to make sure at this point
6281 			// that we are not the focus view anymore.
6282 			if (fOwner->CurrentFocus() == this)
6283 				fOwner->_SetFocus(NULL, true);
6284 		}
6285 
6286 		if (fOwner->fDefaultButton == this)
6287 			fOwner->SetDefaultButton(NULL);
6288 
6289 		if (fOwner->fKeyMenuBar == this)
6290 			fOwner->fKeyMenuBar = NULL;
6291 
6292 		if (fOwner->fLastMouseMovedView == this)
6293 			fOwner->fLastMouseMovedView = NULL;
6294 
6295 		if (fOwner->fLastViewToken == _get_object_token_(this))
6296 			fOwner->fLastViewToken = B_NULL_TOKEN;
6297 
6298 		_SetOwner(NULL);
6299 	}
6300 }
6301 
6302 
6303 void
6304 BView::_Draw(BRect updateRect)
6305 {
6306 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW))
6307 		return;
6308 
6309 	// NOTE: if ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW
6310 	// -> View is simply not drawn at all
6311 
6312 	_SwitchServerCurrentView();
6313 
6314 	ConvertFromScreen(&updateRect);
6315 
6316 	// TODO: make states robust (the hook implementation could
6317 	// mess things up if it uses non-matching Push- and PopState(),
6318 	// we would not be guaranteed to still have the same state on
6319 	// the stack after having called Draw())
6320 	PushState();
6321 	Draw(updateRect);
6322 	PopState();
6323 	Flush();
6324 }
6325 
6326 
6327 void
6328 BView::_DrawAfterChildren(BRect updateRect)
6329 {
6330 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW)
6331 		|| !(Flags() & B_DRAW_ON_CHILDREN))
6332 		return;
6333 
6334 	_SwitchServerCurrentView();
6335 
6336 	ConvertFromScreen(&updateRect);
6337 
6338 	// TODO: make states robust (see above)
6339 	PushState();
6340 	DrawAfterChildren(updateRect);
6341 	PopState();
6342 	Flush();
6343 }
6344 
6345 
6346 void
6347 BView::_FontsUpdated(BMessage* message)
6348 {
6349 	MessageReceived(message);
6350 
6351 	for (BView* child = fFirstChild; child != NULL;
6352 			child = child->fNextSibling) {
6353 		child->_FontsUpdated(message);
6354 	}
6355 }
6356 
6357 
6358 void
6359 BView::_Pulse()
6360 {
6361 	if ((Flags() & B_PULSE_NEEDED) != 0)
6362 		Pulse();
6363 
6364 	for (BView* child = fFirstChild; child != NULL;
6365 			child = child->fNextSibling) {
6366 		child->_Pulse();
6367 	}
6368 }
6369 
6370 
6371 void
6372 BView::_UpdateStateForRemove()
6373 {
6374 	// TODO: _CheckLockAndSwitchCurrent() would be good enough, no?
6375 	if (!_CheckOwnerLockAndSwitchCurrent())
6376 		return;
6377 
6378 	fState->UpdateFrom(*fOwner->fLink);
6379 //	if (!fState->IsValid(B_VIEW_FRAME_BIT)) {
6380 //		fOwner->fLink->StartMessage(AS_VIEW_GET_COORD);
6381 //
6382 //		status_t code;
6383 //		if (fOwner->fLink->FlushWithReply(code) == B_OK
6384 //			&& code == B_OK) {
6385 //			fOwner->fLink->Read<BPoint>(&fParentOffset);
6386 //			fOwner->fLink->Read<BRect>(&fBounds);
6387 //			fState->valid_flags |= B_VIEW_FRAME_BIT;
6388 //		}
6389 //	}
6390 
6391 	// update children as well
6392 
6393 	for (BView* child = fFirstChild; child != NULL;
6394 			child = child->fNextSibling) {
6395 		if (child->fOwner)
6396 			child->_UpdateStateForRemove();
6397 	}
6398 }
6399 
6400 
6401 inline void
6402 BView::_UpdatePattern(::pattern pattern)
6403 {
6404 	if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern)
6405 		return;
6406 
6407 	if (fOwner) {
6408 		_CheckLockAndSwitchCurrent();
6409 
6410 		fOwner->fLink->StartMessage(AS_VIEW_SET_PATTERN);
6411 		fOwner->fLink->Attach< ::pattern>(pattern);
6412 
6413 		fState->valid_flags |= B_VIEW_PATTERN_BIT;
6414 	}
6415 
6416 	fState->pattern = pattern;
6417 }
6418 
6419 
6420 void
6421 BView::_FlushIfNotInTransaction()
6422 {
6423 	if (!fOwner->fInTransaction) {
6424 		fOwner->Flush();
6425 	}
6426 }
6427 
6428 
6429 BShelf*
6430 BView::_Shelf() const
6431 {
6432 	return fShelf;
6433 }
6434 
6435 
6436 void
6437 BView::_SetShelf(BShelf* shelf)
6438 {
6439 	if (fShelf != NULL && fOwner != NULL)
6440 		fOwner->RemoveHandler(fShelf);
6441 
6442 	fShelf = shelf;
6443 
6444 	if (fShelf != NULL && fOwner != NULL)
6445 		fOwner->AddHandler(fShelf);
6446 }
6447 
6448 
6449 status_t
6450 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
6451 	uint32 followFlags, uint32 options)
6452 {
6453 	if (!_CheckOwnerLockAndSwitchCurrent())
6454 		return B_ERROR;
6455 
6456 	int32 serverToken = bitmap ? bitmap->_ServerToken() : -1;
6457 
6458 	fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_BITMAP);
6459 	fOwner->fLink->Attach<int32>(serverToken);
6460 	fOwner->fLink->Attach<BRect>(srcRect);
6461 	fOwner->fLink->Attach<BRect>(dstRect);
6462 	fOwner->fLink->Attach<int32>(followFlags);
6463 	fOwner->fLink->Attach<int32>(options);
6464 
6465 	status_t status = B_ERROR;
6466 	fOwner->fLink->FlushWithReply(status);
6467 
6468 	return status;
6469 }
6470 
6471 
6472 bool
6473 BView::_CheckOwnerLockAndSwitchCurrent() const
6474 {
6475 	STRACE(("BView(%s)::_CheckOwnerLockAndSwitchCurrent()\n", Name()));
6476 
6477 	if (fOwner == NULL) {
6478 		debugger("View method requires owner and doesn't have one.");
6479 		return false;
6480 	}
6481 
6482 	_CheckLockAndSwitchCurrent();
6483 
6484 	return true;
6485 }
6486 
6487 
6488 bool
6489 BView::_CheckOwnerLock() const
6490 {
6491 	if (fOwner) {
6492 		fOwner->check_lock();
6493 		return true;
6494 	} else {
6495 		debugger("View method requires owner and doesn't have one.");
6496 		return false;
6497 	}
6498 }
6499 
6500 
6501 void
6502 BView::_CheckLockAndSwitchCurrent() const
6503 {
6504 	STRACE(("BView(%s)::_CheckLockAndSwitchCurrent()\n", Name()));
6505 
6506 	if (!fOwner)
6507 		return;
6508 
6509 	fOwner->check_lock();
6510 
6511 	_SwitchServerCurrentView();
6512 }
6513 
6514 
6515 void
6516 BView::_CheckLock() const
6517 {
6518 	if (fOwner)
6519 		fOwner->check_lock();
6520 }
6521 
6522 
6523 void
6524 BView::_SwitchServerCurrentView() const
6525 {
6526 	int32 serverToken = _get_object_token_(this);
6527 
6528 	if (fOwner->fLastViewToken != serverToken) {
6529 		STRACE(("contacting app_server... sending token: %" B_PRId32 "\n",
6530 			serverToken));
6531 		fOwner->fLink->StartMessage(AS_SET_CURRENT_VIEW);
6532 		fOwner->fLink->Attach<int32>(serverToken);
6533 
6534 		fOwner->fLastViewToken = serverToken;
6535 	}
6536 }
6537 
6538 
6539 status_t
6540 BView::ScrollWithMouseWheelDelta(BScrollBar* scrollBar, float delta)
6541 {
6542 	if (scrollBar == NULL || delta == 0.0f)
6543 		return B_BAD_VALUE;
6544 
6545 	float smallStep;
6546 	float largeStep;
6547 	scrollBar->GetSteps(&smallStep, &largeStep);
6548 
6549 	// pressing the shift key scrolls faster (following the pseudo-standard set
6550 	// by other desktop environments).
6551 	if ((modifiers() & B_SHIFT_KEY) != 0)
6552 		delta *= largeStep;
6553 	else
6554 		delta *= smallStep * 3;
6555 
6556 	scrollBar->SetValue(scrollBar->Value() + delta);
6557 
6558 	return B_OK;
6559 }
6560 
6561 
6562 #if __GNUC__ == 2
6563 
6564 
6565 extern "C" void
6566 _ReservedView1__5BView(BView* view, BRect rect)
6567 {
6568 	view->BView::DrawAfterChildren(rect);
6569 }
6570 
6571 
6572 extern "C" void
6573 _ReservedView2__5BView(BView* view)
6574 {
6575 	// MinSize()
6576 	perform_data_min_size data;
6577 	view->Perform(PERFORM_CODE_MIN_SIZE, &data);
6578 }
6579 
6580 
6581 extern "C" void
6582 _ReservedView3__5BView(BView* view)
6583 {
6584 	// MaxSize()
6585 	perform_data_max_size data;
6586 	view->Perform(PERFORM_CODE_MAX_SIZE, &data);
6587 }
6588 
6589 
6590 extern "C" BSize
6591 _ReservedView4__5BView(BView* view)
6592 {
6593 	// PreferredSize()
6594 	perform_data_preferred_size data;
6595 	view->Perform(PERFORM_CODE_PREFERRED_SIZE, &data);
6596 	return data.return_value;
6597 }
6598 
6599 
6600 extern "C" BAlignment
6601 _ReservedView5__5BView(BView* view)
6602 {
6603 	// LayoutAlignment()
6604 	perform_data_layout_alignment data;
6605 	view->Perform(PERFORM_CODE_LAYOUT_ALIGNMENT, &data);
6606 	return data.return_value;
6607 }
6608 
6609 
6610 extern "C" bool
6611 _ReservedView6__5BView(BView* view)
6612 {
6613 	// HasHeightForWidth()
6614 	perform_data_has_height_for_width data;
6615 	view->Perform(PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH, &data);
6616 	return data.return_value;
6617 }
6618 
6619 
6620 extern "C" void
6621 _ReservedView7__5BView(BView* view, float width, float* min, float* max,
6622 	float* preferred)
6623 {
6624 	// GetHeightForWidth()
6625 	perform_data_get_height_for_width data;
6626 	data.width = width;
6627 	view->Perform(PERFORM_CODE_GET_HEIGHT_FOR_WIDTH, &data);
6628 	if (min != NULL)
6629 		*min = data.min;
6630 	if (max != NULL)
6631 		*max = data.max;
6632 	if (preferred != NULL)
6633 		*preferred = data.preferred;
6634 }
6635 
6636 
6637 extern "C" void
6638 _ReservedView8__5BView(BView* view, BLayout* layout)
6639 {
6640 	// SetLayout()
6641 	perform_data_set_layout data;
6642 	data.layout = layout;
6643 	view->Perform(PERFORM_CODE_SET_LAYOUT, &data);
6644 }
6645 
6646 
6647 extern "C" void
6648 _ReservedView9__5BView(BView* view, bool descendants)
6649 {
6650 	// LayoutInvalidated()
6651 	perform_data_layout_invalidated data;
6652 	data.descendants = descendants;
6653 	view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
6654 }
6655 
6656 
6657 extern "C" void
6658 _ReservedView10__5BView(BView* view)
6659 {
6660 	// DoLayout()
6661 	view->Perform(PERFORM_CODE_DO_LAYOUT, NULL);
6662 }
6663 
6664 
6665 #endif	// __GNUC__ == 2
6666 
6667 
6668 extern "C" bool
6669 B_IF_GCC_2(_ReservedView11__5BView, _ZN5BView15_ReservedView11Ev)(
6670 	BView* view, BPoint point, BToolTip** _toolTip)
6671 {
6672 	// GetToolTipAt()
6673 	perform_data_get_tool_tip_at data;
6674 	data.point = point;
6675 	data.tool_tip = _toolTip;
6676 	view->Perform(PERFORM_CODE_GET_TOOL_TIP_AT, &data);
6677 	return data.return_value;
6678 }
6679 
6680 
6681 extern "C" void
6682 B_IF_GCC_2(_ReservedView12__5BView, _ZN5BView15_ReservedView12Ev)(
6683 	BView* view)
6684 {
6685 	// LayoutChanged();
6686 	view->Perform(PERFORM_CODE_LAYOUT_CHANGED, NULL);
6687 }
6688 
6689 
6690 void BView::_ReservedView13() {}
6691 void BView::_ReservedView14() {}
6692 void BView::_ReservedView15() {}
6693 void BView::_ReservedView16() {}
6694 
6695 
6696 BView::BView(const BView& other)
6697 	:
6698 	BHandler()
6699 {
6700 	// this is private and not functional, but exported
6701 }
6702 
6703 
6704 BView&
6705 BView::operator=(const BView& other)
6706 {
6707 	// this is private and not functional, but exported
6708 	return *this;
6709 }
6710 
6711 
6712 void
6713 BView::_PrintToStream()
6714 {
6715 	printf("BView::_PrintToStream()\n");
6716 	printf("\tName: %s\n"
6717 		"\tParent: %s\n"
6718 		"\tFirstChild: %s\n"
6719 		"\tNextSibling: %s\n"
6720 		"\tPrevSibling: %s\n"
6721 		"\tOwner(Window): %s\n"
6722 		"\tToken: %" B_PRId32 "\n"
6723 		"\tFlags: %" B_PRId32 "\n"
6724 		"\tView origin: (%f,%f)\n"
6725 		"\tView Bounds rectangle: (%f,%f,%f,%f)\n"
6726 		"\tShow level: %d\n"
6727 		"\tTopView?: %s\n"
6728 		"\tBPicture: %s\n"
6729 		"\tVertical Scrollbar %s\n"
6730 		"\tHorizontal Scrollbar %s\n"
6731 		"\tIs Printing?: %s\n"
6732 		"\tShelf?: %s\n"
6733 		"\tEventMask: %" B_PRId32 "\n"
6734 		"\tEventOptions: %" B_PRId32 "\n",
6735 	Name(),
6736 	fParent ? fParent->Name() : "NULL",
6737 	fFirstChild ? fFirstChild->Name() : "NULL",
6738 	fNextSibling ? fNextSibling->Name() : "NULL",
6739 	fPreviousSibling ? fPreviousSibling->Name() : "NULL",
6740 	fOwner ? fOwner->Name() : "NULL",
6741 	_get_object_token_(this),
6742 	fFlags,
6743 	fParentOffset.x, fParentOffset.y,
6744 	fBounds.left, fBounds.top, fBounds.right, fBounds.bottom,
6745 	fShowLevel,
6746 	fTopLevelView ? "YES" : "NO",
6747 	fCurrentPicture? "YES" : "NULL",
6748 	fVerScroller? "YES" : "NULL",
6749 	fHorScroller? "YES" : "NULL",
6750 	fIsPrinting? "YES" : "NO",
6751 	fShelf? "YES" : "NO",
6752 	fEventMask,
6753 	fEventOptions);
6754 
6755 	printf("\tState status:\n"
6756 		"\t\tLocalCoordianteSystem: (%f,%f)\n"
6757 		"\t\tPenLocation: (%f,%f)\n"
6758 		"\t\tPenSize: %f\n"
6759 		"\t\tHighColor: [%d,%d,%d,%d]\n"
6760 		"\t\tLowColor: [%d,%d,%d,%d]\n"
6761 		"\t\tViewColor: [%d,%d,%d,%d]\n"
6762 		"\t\tPattern: %" B_PRIx64 "\n"
6763 		"\t\tDrawingMode: %d\n"
6764 		"\t\tLineJoinMode: %d\n"
6765 		"\t\tLineCapMode: %d\n"
6766 		"\t\tMiterLimit: %f\n"
6767 		"\t\tAlphaSource: %d\n"
6768 		"\t\tAlphaFuntion: %d\n"
6769 		"\t\tScale: %f\n"
6770 		"\t\t(Print)FontAliasing: %s\n"
6771 		"\t\tFont Info:\n",
6772 	fState->origin.x, fState->origin.y,
6773 	fState->pen_location.x, fState->pen_location.y,
6774 	fState->pen_size,
6775 	fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha,
6776 	fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha,
6777 	fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha,
6778 	*((uint64*)&(fState->pattern)),
6779 	fState->drawing_mode,
6780 	fState->line_join,
6781 	fState->line_cap,
6782 	fState->miter_limit,
6783 	fState->alpha_source_mode,
6784 	fState->alpha_function_mode,
6785 	fState->scale,
6786 	fState->font_aliasing? "YES" : "NO");
6787 
6788 	fState->font.PrintToStream();
6789 
6790 	// TODO: also print the line array.
6791 }
6792 
6793 
6794 void
6795 BView::_PrintTree()
6796 {
6797 	int32 spaces = 2;
6798 	BView* c = fFirstChild; //c = short for: current
6799 	printf( "'%s'\n", Name() );
6800 	if (c != NULL) {
6801 		while(true) {
6802 			// action block
6803 			{
6804 				for (int i = 0; i < spaces; i++)
6805 					printf(" ");
6806 
6807 				printf( "'%s'\n", c->Name() );
6808 			}
6809 
6810 			// go deep
6811 			if (c->fFirstChild) {
6812 				c = c->fFirstChild;
6813 				spaces += 2;
6814 			} else {
6815 				// go right
6816 				if (c->fNextSibling) {
6817 					c = c->fNextSibling;
6818 				} else {
6819 					// go up
6820 					while (!c->fParent->fNextSibling && c->fParent != this) {
6821 						c = c->fParent;
6822 						spaces -= 2;
6823 					}
6824 
6825 					// that enough! We've reached this view.
6826 					if (c->fParent == this)
6827 						break;
6828 
6829 					c = c->fParent->fNextSibling;
6830 					spaces -= 2;
6831 				}
6832 			}
6833 		}
6834 	}
6835 }
6836 
6837 
6838 // #pragma mark -
6839 
6840 
6841 BLayoutItem*
6842 BView::Private::LayoutItemAt(int32 index)
6843 {
6844 	return fView->fLayoutData->fLayoutItems.ItemAt(index);
6845 }
6846 
6847 
6848 int32
6849 BView::Private::CountLayoutItems()
6850 {
6851 	return fView->fLayoutData->fLayoutItems.CountItems();
6852 }
6853 
6854 
6855 void
6856 BView::Private::RegisterLayoutItem(BLayoutItem* item)
6857 {
6858 	fView->fLayoutData->fLayoutItems.AddItem(item);
6859 }
6860 
6861 
6862 void
6863 BView::Private::DeregisterLayoutItem(BLayoutItem* item)
6864 {
6865 	fView->fLayoutData->fLayoutItems.RemoveItem(item);
6866 }
6867 
6868 
6869 bool
6870 BView::Private::MinMaxValid()
6871 {
6872 	return fView->fLayoutData->fMinMaxValid;
6873 }
6874 
6875 
6876 bool
6877 BView::Private::WillLayout()
6878 {
6879 	BView::LayoutData* data = fView->fLayoutData;
6880 	if (data->fLayoutInProgress)
6881 		return false;
6882 	if (data->fNeedsRelayout || !data->fLayoutValid || !data->fMinMaxValid)
6883 		return true;
6884 	return false;
6885 }
6886