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