xref: /haiku/src/kits/interface/View.cpp (revision bf57c148f7787f0df15980976997c6dfb70ee067)
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->count = 0;
3642 
3643 	// Make sure the fCommArray is initialized to reasonable values in cases of
3644 	// bad_alloc. At least the exception can be caught and EndLineArray won't
3645 	// crash.
3646 	fCommArray->array = NULL;
3647 	fCommArray->maxCount = 0;
3648 
3649 	fCommArray->array = new ViewLineArrayInfo[count];
3650 	fCommArray->maxCount = count;
3651 }
3652 
3653 
3654 void
3655 BView::AddLine(BPoint start, BPoint end, rgb_color color)
3656 {
3657 	if (fOwner == NULL)
3658 		return;
3659 
3660 	if (!fCommArray)
3661 		debugger("BeginLineArray must be called before using AddLine");
3662 
3663 	_CheckLock();
3664 
3665 	const uint32 &arrayCount = fCommArray->count;
3666 	if (arrayCount < fCommArray->maxCount) {
3667 		fCommArray->array[arrayCount].startPoint = start;
3668 		fCommArray->array[arrayCount].endPoint = end;
3669 		fCommArray->array[arrayCount].color = color;
3670 
3671 		fCommArray->count++;
3672 	}
3673 }
3674 
3675 
3676 void
3677 BView::EndLineArray()
3678 {
3679 	if (fOwner == NULL)
3680 		return;
3681 
3682 	if (fCommArray == NULL)
3683 		debugger("Can't call EndLineArray before BeginLineArray");
3684 
3685 	_CheckLockAndSwitchCurrent();
3686 
3687 	fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY);
3688 	fOwner->fLink->Attach<int32>(fCommArray->count);
3689 	fOwner->fLink->Attach(fCommArray->array,
3690 		fCommArray->count * sizeof(ViewLineArrayInfo));
3691 
3692 	_FlushIfNotInTransaction();
3693 
3694 	_RemoveCommArray();
3695 }
3696 
3697 
3698 void
3699 BView::SetDiskMode(char* filename, long offset)
3700 {
3701 	// TODO: implement
3702 	// One BeBook version has this to say about SetDiskMode():
3703 	//
3704 	// "Begins recording a picture to the file with the given filename
3705 	// at the given offset. Subsequent drawing commands sent to the view
3706 	// will be written to the file until EndPicture() is called. The
3707 	// stored commands may be played from the file with DrawPicture()."
3708 }
3709 
3710 
3711 void
3712 BView::BeginPicture(BPicture* picture)
3713 {
3714 	if (_CheckOwnerLockAndSwitchCurrent()
3715 		&& picture && picture->fUsurped == NULL) {
3716 		picture->Usurp(fCurrentPicture);
3717 		fCurrentPicture = picture;
3718 
3719 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_PICTURE);
3720 	}
3721 }
3722 
3723 
3724 void
3725 BView::AppendToPicture(BPicture* picture)
3726 {
3727 	_CheckLockAndSwitchCurrent();
3728 
3729 	if (picture && picture->fUsurped == NULL) {
3730 		int32 token = picture->Token();
3731 
3732 		if (token == -1) {
3733 			BeginPicture(picture);
3734 		} else {
3735 			picture->SetToken(-1);
3736 			picture->Usurp(fCurrentPicture);
3737 			fCurrentPicture = picture;
3738 			fOwner->fLink->StartMessage(AS_VIEW_APPEND_TO_PICTURE);
3739 			fOwner->fLink->Attach<int32>(token);
3740 		}
3741 	}
3742 }
3743 
3744 
3745 BPicture*
3746 BView::EndPicture()
3747 {
3748 	if (_CheckOwnerLockAndSwitchCurrent() && fCurrentPicture) {
3749 		int32 token;
3750 
3751 		fOwner->fLink->StartMessage(AS_VIEW_END_PICTURE);
3752 
3753 		int32 code;
3754 		if (fOwner->fLink->FlushWithReply(code) == B_OK
3755 			&& code == B_OK
3756 			&& fOwner->fLink->Read<int32>(&token) == B_OK) {
3757 			BPicture* picture = fCurrentPicture;
3758 			fCurrentPicture = picture->StepDown();
3759 			picture->SetToken(token);
3760 
3761 			// TODO do this more efficient e.g. use a shared area and let the
3762 			// client write into it
3763 			picture->_Download();
3764 			return picture;
3765 		}
3766 	}
3767 
3768 	return NULL;
3769 }
3770 
3771 
3772 void
3773 BView::SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
3774 	uint32 followFlags, uint32 options)
3775 {
3776 	_SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options);
3777 }
3778 
3779 
3780 void
3781 BView::SetViewBitmap(const BBitmap* bitmap, uint32 followFlags, uint32 options)
3782 {
3783 	BRect rect;
3784  	if (bitmap)
3785 		rect = bitmap->Bounds();
3786 
3787  	rect.OffsetTo(B_ORIGIN);
3788 
3789 	_SetViewBitmap(bitmap, rect, rect, followFlags, options);
3790 }
3791 
3792 
3793 void
3794 BView::ClearViewBitmap()
3795 {
3796 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
3797 }
3798 
3799 
3800 status_t
3801 BView::SetViewOverlay(const BBitmap* overlay, BRect srcRect, BRect dstRect,
3802 	rgb_color* colorKey, uint32 followFlags, uint32 options)
3803 {
3804 	if (overlay == NULL || (overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0)
3805 		return B_BAD_VALUE;
3806 
3807 	status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags,
3808 		options | AS_REQUEST_COLOR_KEY);
3809 	if (status == B_OK) {
3810 		// read the color that will be treated as transparent
3811 		fOwner->fLink->Read<rgb_color>(colorKey);
3812 	}
3813 
3814 	return status;
3815 }
3816 
3817 
3818 status_t
3819 BView::SetViewOverlay(const BBitmap* overlay, rgb_color* colorKey,
3820 	uint32 followFlags, uint32 options)
3821 {
3822 	if (overlay == NULL)
3823 		return B_BAD_VALUE;
3824 
3825 	BRect rect = overlay->Bounds();
3826  	rect.OffsetTo(B_ORIGIN);
3827 
3828 	return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options);
3829 }
3830 
3831 
3832 void
3833 BView::ClearViewOverlay()
3834 {
3835 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
3836 }
3837 
3838 
3839 void
3840 BView::CopyBits(BRect src, BRect dst)
3841 {
3842 	if (fOwner == NULL)
3843 		return;
3844 
3845 	if (!src.IsValid() || !dst.IsValid())
3846 		return;
3847 
3848 	_CheckLockAndSwitchCurrent();
3849 
3850 	fOwner->fLink->StartMessage(AS_VIEW_COPY_BITS);
3851 	fOwner->fLink->Attach<BRect>(src);
3852 	fOwner->fLink->Attach<BRect>(dst);
3853 
3854 	_FlushIfNotInTransaction();
3855 }
3856 
3857 
3858 void
3859 BView::DrawPicture(const BPicture* picture)
3860 {
3861 	if (picture == NULL)
3862 		return;
3863 
3864 	DrawPictureAsync(picture, PenLocation());
3865 	Sync();
3866 }
3867 
3868 
3869 void
3870 BView::DrawPicture(const BPicture* picture, BPoint where)
3871 {
3872 	if (picture == NULL)
3873 		return;
3874 
3875 	DrawPictureAsync(picture, where);
3876 	Sync();
3877 }
3878 
3879 
3880 void
3881 BView::DrawPicture(const char* filename, long offset, BPoint where)
3882 {
3883 	if (!filename)
3884 		return;
3885 
3886 	DrawPictureAsync(filename, offset, where);
3887 	Sync();
3888 }
3889 
3890 
3891 void
3892 BView::DrawPictureAsync(const BPicture* picture)
3893 {
3894 	if (picture == NULL)
3895 		return;
3896 
3897 	DrawPictureAsync(picture, PenLocation());
3898 }
3899 
3900 
3901 void
3902 BView::DrawPictureAsync(const BPicture* picture, BPoint where)
3903 {
3904 	if (picture == NULL)
3905 		return;
3906 
3907 	if (_CheckOwnerLockAndSwitchCurrent() && picture->Token() > 0) {
3908 		fOwner->fLink->StartMessage(AS_VIEW_DRAW_PICTURE);
3909 		fOwner->fLink->Attach<int32>(picture->Token());
3910 		fOwner->fLink->Attach<BPoint>(where);
3911 
3912 		_FlushIfNotInTransaction();
3913 	}
3914 }
3915 
3916 
3917 void
3918 BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
3919 {
3920 	if (!filename)
3921 		return;
3922 
3923 	// TODO: Test
3924 	BFile file(filename, B_READ_ONLY);
3925 	if (file.InitCheck() < B_OK)
3926 		return;
3927 
3928 	file.Seek(offset, SEEK_SET);
3929 
3930 	BPicture picture;
3931 	if (picture.Unflatten(&file) < B_OK)
3932 		return;
3933 
3934 	DrawPictureAsync(&picture, where);
3935 }
3936 
3937 
3938 void
3939 BView::Invalidate(BRect invalRect)
3940 {
3941 	if (fOwner == NULL)
3942 		return;
3943 
3944 	// NOTE: This rounding of the invalid rect is to stay compatible with BeOS.
3945 	// On the server side, the invalid rect will be converted to a BRegion,
3946 	// which rounds in a different manner, so that it really includes the
3947 	// fractional coordinates of a BRect (ie ceilf(rect.right) &
3948 	// ceilf(rect.bottom)), which is also what BeOS does. So we have to do the
3949 	// different rounding here to stay compatible in both ways.
3950 	invalRect.left = (int)invalRect.left;
3951 	invalRect.top = (int)invalRect.top;
3952 	invalRect.right = (int)invalRect.right;
3953 	invalRect.bottom = (int)invalRect.bottom;
3954 	if (!invalRect.IsValid())
3955 		return;
3956 
3957 	_CheckLockAndSwitchCurrent();
3958 
3959 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_RECT);
3960 	fOwner->fLink->Attach<BRect>(invalRect);
3961 
3962 // TODO: determine why this check isn't working correctly.
3963 #if 0
3964 	if (!fOwner->fUpdateRequested) {
3965 		fOwner->fLink->Flush();
3966 		fOwner->fUpdateRequested = true;
3967 	}
3968 #else
3969 	fOwner->fLink->Flush();
3970 #endif
3971 }
3972 
3973 
3974 void
3975 BView::Invalidate(const BRegion* region)
3976 {
3977 	if (region == NULL || fOwner == NULL)
3978 		return;
3979 
3980 	_CheckLockAndSwitchCurrent();
3981 
3982 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_REGION);
3983 	fOwner->fLink->AttachRegion(*region);
3984 
3985 // TODO: See above.
3986 #if 0
3987 	if (!fOwner->fUpdateRequested) {
3988 		fOwner->fLink->Flush();
3989 		fOwner->fUpdateRequested = true;
3990 	}
3991 #else
3992 	fOwner->fLink->Flush();
3993 #endif
3994 }
3995 
3996 
3997 void
3998 BView::Invalidate()
3999 {
4000 	Invalidate(Bounds());
4001 }
4002 
4003 
4004 void
4005 BView::InvertRect(BRect rect)
4006 {
4007 	if (fOwner) {
4008 		_CheckLockAndSwitchCurrent();
4009 
4010 		fOwner->fLink->StartMessage(AS_VIEW_INVERT_RECT);
4011 		fOwner->fLink->Attach<BRect>(rect);
4012 
4013 		_FlushIfNotInTransaction();
4014 	}
4015 }
4016 
4017 
4018 //	#pragma mark - View Hierarchy Functions
4019 
4020 
4021 void
4022 BView::AddChild(BView* child, BView* before)
4023 {
4024 	STRACE(("BView(%s)::AddChild(child '%s', before '%s')\n",
4025  		this->Name(),
4026  		child != NULL && child->Name() ? child->Name() : "NULL",
4027  		before != NULL && before->Name() ? before->Name() : "NULL"));
4028 
4029 	if (!_AddChild(child, before))
4030 		return;
4031 
4032 	if (fLayoutData->fLayout)
4033 		fLayoutData->fLayout->AddView(child);
4034 }
4035 
4036 
4037 bool
4038 BView::AddChild(BLayoutItem* child)
4039 {
4040 	if (!fLayoutData->fLayout)
4041 		return false;
4042 	return fLayoutData->fLayout->AddItem(child);
4043 }
4044 
4045 
4046 bool
4047 BView::_AddChild(BView* child, BView* before)
4048 {
4049 	if (!child)
4050 		return false;
4051 
4052 	if (child->fParent != NULL) {
4053 		debugger("AddChild failed - the view already has a parent.");
4054 		return false;
4055 	}
4056 
4057 	if (child == this) {
4058 		debugger("AddChild failed - cannot add a view to itself.");
4059 		return false;
4060 	}
4061 
4062 	bool lockedOwner = false;
4063 	if (fOwner && !fOwner->IsLocked()) {
4064 		fOwner->Lock();
4065 		lockedOwner = true;
4066 	}
4067 
4068 	if (!_AddChildToList(child, before)) {
4069 		debugger("AddChild failed!");
4070 		if (lockedOwner)
4071 			fOwner->Unlock();
4072 		return false;
4073 	}
4074 
4075 	if (fOwner) {
4076 		_CheckLockAndSwitchCurrent();
4077 
4078 		child->_SetOwner(fOwner);
4079 		child->_CreateSelf();
4080 		child->_Attach();
4081 
4082 		if (lockedOwner)
4083 			fOwner->Unlock();
4084 	}
4085 
4086 	InvalidateLayout();
4087 
4088 	return true;
4089 }
4090 
4091 
4092 bool
4093 BView::RemoveChild(BView* child)
4094 {
4095 	STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name()));
4096 
4097 	if (!child)
4098 		return false;
4099 
4100 	if (child->fParent != this)
4101 		return false;
4102 
4103 	return child->RemoveSelf();
4104 }
4105 
4106 
4107 int32
4108 BView::CountChildren() const
4109 {
4110 	_CheckLock();
4111 
4112 	uint32 count = 0;
4113 	BView* child = fFirstChild;
4114 
4115 	while (child != NULL) {
4116 		count++;
4117 		child = child->fNextSibling;
4118 	}
4119 
4120 	return count;
4121 }
4122 
4123 
4124 BView*
4125 BView::ChildAt(int32 index) const
4126 {
4127 	_CheckLock();
4128 
4129 	BView* child = fFirstChild;
4130 	while (child != NULL && index-- > 0) {
4131 		child = child->fNextSibling;
4132 	}
4133 
4134 	return child;
4135 }
4136 
4137 
4138 BView*
4139 BView::NextSibling() const
4140 {
4141 	return fNextSibling;
4142 }
4143 
4144 
4145 BView*
4146 BView::PreviousSibling() const
4147 {
4148 	return fPreviousSibling;
4149 }
4150 
4151 
4152 bool
4153 BView::RemoveSelf()
4154 {
4155 	if (fParent && fParent->fLayoutData->fLayout) {
4156 		int32 itemsRemaining = fLayoutData->fLayoutItems.CountItems();
4157 		while (itemsRemaining-- > 0) {
4158 			BLayoutItem* item = fLayoutData->fLayoutItems.ItemAt(0);
4159 				// always remove item at index 0, since items are shuffled
4160 				// downwards by BObjectList
4161 			item->Layout()->RemoveItem(item);
4162 				// removes item from fLayoutItems list
4163 			delete item;
4164 		}
4165 	}
4166 
4167 	return _RemoveSelf();
4168 }
4169 
4170 
4171 bool
4172 BView::_RemoveSelf()
4173 {
4174 	STRACE(("BView(%s)::_RemoveSelf()\n", Name()));
4175 
4176 	// Remove this child from its parent
4177 
4178 	BWindow* owner = fOwner;
4179 	_CheckLock();
4180 
4181 	if (owner != NULL) {
4182 		_UpdateStateForRemove();
4183 		_Detach();
4184 	}
4185 
4186 	BView* parent = fParent;
4187 	if (!parent || !parent->_RemoveChildFromList(this))
4188 		return false;
4189 
4190 	if (owner != NULL && !fTopLevelView) {
4191 		// the top level view is deleted by the app_server automatically
4192 		owner->fLink->StartMessage(AS_VIEW_DELETE);
4193 		owner->fLink->Attach<int32>(_get_object_token_(this));
4194 	}
4195 
4196 	parent->InvalidateLayout();
4197 
4198 	STRACE(("DONE: BView(%s)::_RemoveSelf()\n", Name()));
4199 
4200 	return true;
4201 }
4202 
4203 
4204 BView*
4205 BView::Parent() const
4206 {
4207 	if (fParent && fParent->fTopLevelView)
4208 		return NULL;
4209 
4210 	return fParent;
4211 }
4212 
4213 
4214 BView*
4215 BView::FindView(const char* name) const
4216 {
4217 	if (name == NULL)
4218 		return NULL;
4219 
4220 	if (Name() != NULL && !strcmp(Name(), name))
4221 		return const_cast<BView*>(this);
4222 
4223 	BView* child = fFirstChild;
4224 	while (child != NULL) {
4225 		BView* view = child->FindView(name);
4226 		if (view != NULL)
4227 			return view;
4228 
4229 		child = child->fNextSibling;
4230 	}
4231 
4232 	return NULL;
4233 }
4234 
4235 
4236 void
4237 BView::MoveBy(float deltaX, float deltaY)
4238 {
4239 	MoveTo(fParentOffset.x + roundf(deltaX), fParentOffset.y + roundf(deltaY));
4240 }
4241 
4242 
4243 void
4244 BView::MoveTo(BPoint where)
4245 {
4246 	MoveTo(where.x, where.y);
4247 }
4248 
4249 
4250 void
4251 BView::MoveTo(float x, float y)
4252 {
4253 	if (x == fParentOffset.x && y == fParentOffset.y)
4254 		return;
4255 
4256 	// BeBook says we should do this. And it makes sense.
4257 	x = roundf(x);
4258 	y = roundf(y);
4259 
4260 	if (fOwner) {
4261 		_CheckLockAndSwitchCurrent();
4262 		fOwner->fLink->StartMessage(AS_VIEW_MOVE_TO);
4263 		fOwner->fLink->Attach<float>(x);
4264 		fOwner->fLink->Attach<float>(y);
4265 
4266 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4267 
4268 		_FlushIfNotInTransaction();
4269 	}
4270 
4271 	_MoveTo((int32)x, (int32)y);
4272 }
4273 
4274 
4275 void
4276 BView::ResizeBy(float deltaWidth, float deltaHeight)
4277 {
4278 	// BeBook says we should do this. And it makes sense.
4279 	deltaWidth = roundf(deltaWidth);
4280 	deltaHeight = roundf(deltaHeight);
4281 
4282 	if (deltaWidth == 0 && deltaHeight == 0)
4283 		return;
4284 
4285 	if (fOwner) {
4286 		_CheckLockAndSwitchCurrent();
4287 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_TO);
4288 
4289 		fOwner->fLink->Attach<float>(fBounds.Width() + deltaWidth);
4290 		fOwner->fLink->Attach<float>(fBounds.Height() + deltaHeight);
4291 
4292 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4293 
4294 		_FlushIfNotInTransaction();
4295 	}
4296 
4297 	_ResizeBy((int32)deltaWidth, (int32)deltaHeight);
4298 }
4299 
4300 
4301 void
4302 BView::ResizeTo(float width, float height)
4303 {
4304 	ResizeBy(width - fBounds.Width(), height - fBounds.Height());
4305 }
4306 
4307 
4308 void
4309 BView::ResizeTo(BSize size)
4310 {
4311 	ResizeBy(size.width - fBounds.Width(), size.height - fBounds.Height());
4312 }
4313 
4314 
4315 //	#pragma mark - Inherited Methods (from BHandler)
4316 
4317 
4318 status_t
4319 BView::GetSupportedSuites(BMessage* data)
4320 {
4321 	if (data == NULL)
4322 		return B_BAD_VALUE;
4323 
4324 	status_t status = data->AddString("suites", "suite/vnd.Be-view");
4325 	BPropertyInfo propertyInfo(sViewPropInfo);
4326 	if (status == B_OK)
4327 		status = data->AddFlat("messages", &propertyInfo);
4328 	if (status == B_OK)
4329 		return BHandler::GetSupportedSuites(data);
4330 	return status;
4331 }
4332 
4333 
4334 BHandler*
4335 BView::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
4336 	int32 what, const char* property)
4337 {
4338 	if (message->what == B_WINDOW_MOVE_BY
4339 		|| message->what == B_WINDOW_MOVE_TO) {
4340 		return this;
4341 	}
4342 
4343 	BPropertyInfo propertyInfo(sViewPropInfo);
4344 	status_t err = B_BAD_SCRIPT_SYNTAX;
4345 	BMessage replyMsg(B_REPLY);
4346 
4347 	switch (propertyInfo.FindMatch(message, index, specifier, what, property)) {
4348 		case 0:
4349 		case 1:
4350 		case 3:
4351 			return this;
4352 
4353 		case 2:
4354 			if (fShelf) {
4355 				message->PopSpecifier();
4356 				return fShelf;
4357 			}
4358 
4359 			err = B_NAME_NOT_FOUND;
4360 			replyMsg.AddString("message", "This window doesn't have a shelf");
4361 			break;
4362 
4363 		case 4:
4364 		{
4365 			if (!fFirstChild) {
4366 				err = B_NAME_NOT_FOUND;
4367 				replyMsg.AddString("message", "This window doesn't have "
4368 					"children.");
4369 				break;
4370 			}
4371 			BView* child = NULL;
4372 			switch (what) {
4373 				case B_INDEX_SPECIFIER:
4374 				{
4375 					int32 index;
4376 					err = specifier->FindInt32("index", &index);
4377 					if (err == B_OK)
4378 						child = ChildAt(index);
4379 					break;
4380 				}
4381 				case B_REVERSE_INDEX_SPECIFIER:
4382 				{
4383 					int32 rindex;
4384 					err = specifier->FindInt32("index", &rindex);
4385 					if (err == B_OK)
4386 						child = ChildAt(CountChildren() - rindex);
4387 					break;
4388 				}
4389 				case B_NAME_SPECIFIER:
4390 				{
4391 					const char* name;
4392 					err = specifier->FindString("name", &name);
4393 					if (err == B_OK)
4394 						child = FindView(name);
4395 					break;
4396 				}
4397 			}
4398 
4399 			if (child != NULL) {
4400 				message->PopSpecifier();
4401 				return child;
4402 			}
4403 
4404 			if (err == B_OK)
4405 				err = B_BAD_INDEX;
4406 
4407 			replyMsg.AddString("message",
4408 				"Cannot find view at/with specified index/name.");
4409 			break;
4410 		}
4411 
4412 		default:
4413 			return BHandler::ResolveSpecifier(message, index, specifier, what,
4414 				property);
4415 	}
4416 
4417 	if (err < B_OK) {
4418 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
4419 
4420 		if (err == B_BAD_SCRIPT_SYNTAX)
4421 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
4422 		else
4423 			replyMsg.AddString("message", strerror(err));
4424 	}
4425 
4426 	replyMsg.AddInt32("error", err);
4427 	message->SendReply(&replyMsg);
4428 	return NULL;
4429 }
4430 
4431 
4432 void
4433 BView::MessageReceived(BMessage* message)
4434 {
4435 	if (!message->HasSpecifiers()) {
4436 		switch (message->what) {
4437 			case B_VIEW_RESIZED:
4438 				// By the time the message arrives, the bounds may have
4439 				// changed already, that's why we don't use the values
4440 				// in the message itself.
4441 				FrameResized(fBounds.Width(), fBounds.Height());
4442 				break;
4443 
4444 			case B_VIEW_MOVED:
4445 				FrameMoved(fParentOffset);
4446 				break;
4447 
4448 			case B_MOUSE_IDLE:
4449 			{
4450 				BPoint where;
4451 				if (message->FindPoint("be:view_where", &where) != B_OK)
4452 					break;
4453 
4454 				BToolTip* tip;
4455 				if (GetToolTipAt(where, &tip))
4456 					ShowToolTip(tip);
4457 				else
4458 					BHandler::MessageReceived(message);
4459 				break;
4460 			}
4461 
4462 			case B_MOUSE_WHEEL_CHANGED:
4463 			{
4464 				BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
4465 				BScrollBar* vertical = ScrollBar(B_VERTICAL);
4466 				if (horizontal == NULL && vertical == NULL) {
4467 					// Pass the message to the next handler
4468 					BHandler::MessageReceived(message);
4469 					break;
4470 				}
4471 
4472 				float deltaX = 0.0f;
4473 				float deltaY = 0.0f;
4474 
4475 				if (horizontal != NULL)
4476 					message->FindFloat("be:wheel_delta_x", &deltaX);
4477 
4478 				if (vertical != NULL)
4479 					message->FindFloat("be:wheel_delta_y", &deltaY);
4480 
4481 				if (deltaX == 0.0f && deltaY == 0.0f)
4482 					break;
4483 
4484 				if ((modifiers() & B_CONTROL_KEY) != 0)
4485 					std::swap(horizontal, vertical);
4486 
4487 				if (horizontal != NULL && deltaX != 0.0f)
4488 					ScrollWithMouseWheelDelta(horizontal, deltaX);
4489 
4490 				if (vertical != NULL && deltaY != 0.0f)
4491 					ScrollWithMouseWheelDelta(vertical, deltaY);
4492 
4493 				break;
4494 			}
4495 
4496 			default:
4497 				BHandler::MessageReceived(message);
4498 				break;
4499 		}
4500 
4501 		return;
4502 	}
4503 
4504 	// Scripting message
4505 
4506 	BMessage replyMsg(B_REPLY);
4507 	status_t err = B_BAD_SCRIPT_SYNTAX;
4508 	int32 index;
4509 	BMessage specifier;
4510 	int32 what;
4511 	const char* property;
4512 
4513 	if (message->GetCurrentSpecifier(&index, &specifier, &what, &property)
4514 			!= B_OK) {
4515 		return BHandler::MessageReceived(message);
4516 	}
4517 
4518 	BPropertyInfo propertyInfo(sViewPropInfo);
4519 	switch (propertyInfo.FindMatch(message, index, &specifier, what,
4520 			property)) {
4521 		case 0:
4522 			if (message->what == B_GET_PROPERTY) {
4523 				err = replyMsg.AddRect("result", Frame());
4524 			} else if (message->what == B_SET_PROPERTY) {
4525 				BRect newFrame;
4526 				err = message->FindRect("data", &newFrame);
4527 				if (err == B_OK) {
4528 					MoveTo(newFrame.LeftTop());
4529 					ResizeTo(newFrame.Width(), newFrame.Height());
4530 				}
4531 			}
4532 			break;
4533 		case 1:
4534 			if (message->what == B_GET_PROPERTY) {
4535 				err = replyMsg.AddBool("result", IsHidden());
4536 			} else if (message->what == B_SET_PROPERTY) {
4537 				bool newHiddenState;
4538 				err = message->FindBool("data", &newHiddenState);
4539 				if (err == B_OK) {
4540 					if (newHiddenState == true)
4541 						Hide();
4542 					else
4543 						Show();
4544 				}
4545 			}
4546 			break;
4547 		case 3:
4548 			err = replyMsg.AddInt32("result", CountChildren());
4549 			break;
4550 		default:
4551 			return BHandler::MessageReceived(message);
4552 	}
4553 
4554 	if (err != B_OK) {
4555 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
4556 
4557 		if (err == B_BAD_SCRIPT_SYNTAX)
4558 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
4559 		else
4560 			replyMsg.AddString("message", strerror(err));
4561 
4562 		replyMsg.AddInt32("error", err);
4563 	}
4564 
4565 	message->SendReply(&replyMsg);
4566 }
4567 
4568 
4569 status_t
4570 BView::Perform(perform_code code, void* _data)
4571 {
4572 	switch (code) {
4573 		case PERFORM_CODE_MIN_SIZE:
4574 			((perform_data_min_size*)_data)->return_value
4575 				= BView::MinSize();
4576 			return B_OK;
4577 		case PERFORM_CODE_MAX_SIZE:
4578 			((perform_data_max_size*)_data)->return_value
4579 				= BView::MaxSize();
4580 			return B_OK;
4581 		case PERFORM_CODE_PREFERRED_SIZE:
4582 			((perform_data_preferred_size*)_data)->return_value
4583 				= BView::PreferredSize();
4584 			return B_OK;
4585 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
4586 			((perform_data_layout_alignment*)_data)->return_value
4587 				= BView::LayoutAlignment();
4588 			return B_OK;
4589 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
4590 			((perform_data_has_height_for_width*)_data)->return_value
4591 				= BView::HasHeightForWidth();
4592 			return B_OK;
4593 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
4594 		{
4595 			perform_data_get_height_for_width* data
4596 				= (perform_data_get_height_for_width*)_data;
4597 			BView::GetHeightForWidth(data->width, &data->min, &data->max,
4598 				&data->preferred);
4599 			return B_OK;
4600 		}
4601 		case PERFORM_CODE_SET_LAYOUT:
4602 		{
4603 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
4604 			BView::SetLayout(data->layout);
4605 			return B_OK;
4606 		}
4607 		case PERFORM_CODE_LAYOUT_INVALIDATED:
4608 		{
4609 			perform_data_layout_invalidated* data
4610 				= (perform_data_layout_invalidated*)_data;
4611 			BView::LayoutInvalidated(data->descendants);
4612 			return B_OK;
4613 		}
4614 		case PERFORM_CODE_DO_LAYOUT:
4615 		{
4616 			BView::DoLayout();
4617 			return B_OK;
4618 		}
4619 		case PERFORM_CODE_LAYOUT_CHANGED:
4620 		{
4621 			BView::LayoutChanged();
4622 			return B_OK;
4623 		}
4624 		case PERFORM_CODE_GET_TOOL_TIP_AT:
4625 		{
4626 			perform_data_get_tool_tip_at* data
4627 				= (perform_data_get_tool_tip_at*)_data;
4628 			data->return_value
4629 				= BView::GetToolTipAt(data->point, data->tool_tip);
4630 			return B_OK;
4631 		}
4632 		case PERFORM_CODE_ALL_UNARCHIVED:
4633 		{
4634 			perform_data_all_unarchived* data =
4635 				(perform_data_all_unarchived*)_data;
4636 
4637 			data->return_value = BView::AllUnarchived(data->archive);
4638 			return B_OK;
4639 		}
4640 		case PERFORM_CODE_ALL_ARCHIVED:
4641 		{
4642 			perform_data_all_archived* data =
4643 				(perform_data_all_archived*)_data;
4644 
4645 			data->return_value = BView::AllArchived(data->archive);
4646 			return B_OK;
4647 		}
4648 	}
4649 
4650 	return BHandler::Perform(code, _data);
4651 }
4652 
4653 
4654 // #pragma mark - Layout Functions
4655 
4656 
4657 BSize
4658 BView::MinSize()
4659 {
4660 	// TODO: make sure this works correctly when some methods are overridden
4661 	float width, height;
4662 	GetPreferredSize(&width, &height);
4663 
4664 	return BLayoutUtils::ComposeSize(fLayoutData->fMinSize,
4665 		(fLayoutData->fLayout ? fLayoutData->fLayout->MinSize()
4666 			: BSize(width, height)));
4667 }
4668 
4669 
4670 BSize
4671 BView::MaxSize()
4672 {
4673 	return BLayoutUtils::ComposeSize(fLayoutData->fMaxSize,
4674 		(fLayoutData->fLayout ? fLayoutData->fLayout->MaxSize()
4675 			: BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)));
4676 }
4677 
4678 
4679 BSize
4680 BView::PreferredSize()
4681 {
4682 	// TODO: make sure this works correctly when some methods are overridden
4683 	float width, height;
4684 	GetPreferredSize(&width, &height);
4685 
4686 	return BLayoutUtils::ComposeSize(fLayoutData->fPreferredSize,
4687 		(fLayoutData->fLayout ? fLayoutData->fLayout->PreferredSize()
4688 			: BSize(width, height)));
4689 }
4690 
4691 
4692 BAlignment
4693 BView::LayoutAlignment()
4694 {
4695 	return BLayoutUtils::ComposeAlignment(fLayoutData->fAlignment,
4696 		(fLayoutData->fLayout ? fLayoutData->fLayout->Alignment()
4697 			: BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER)));
4698 }
4699 
4700 
4701 void
4702 BView::SetExplicitMinSize(BSize size)
4703 {
4704 	fLayoutData->fMinSize = size;
4705 	InvalidateLayout();
4706 }
4707 
4708 
4709 void
4710 BView::SetExplicitMaxSize(BSize size)
4711 {
4712 	fLayoutData->fMaxSize = size;
4713 	InvalidateLayout();
4714 }
4715 
4716 
4717 void
4718 BView::SetExplicitPreferredSize(BSize size)
4719 {
4720 	fLayoutData->fPreferredSize = size;
4721 	InvalidateLayout();
4722 }
4723 
4724 
4725 void
4726 BView::SetExplicitSize(BSize size)
4727 {
4728 	fLayoutData->fMinSize = size;
4729 	fLayoutData->fMaxSize = size;
4730 	fLayoutData->fPreferredSize = size;
4731 	InvalidateLayout();
4732 }
4733 
4734 
4735 void
4736 BView::SetExplicitAlignment(BAlignment alignment)
4737 {
4738 	fLayoutData->fAlignment = alignment;
4739 	InvalidateLayout();
4740 }
4741 
4742 
4743 BSize
4744 BView::ExplicitMinSize() const
4745 {
4746 	return fLayoutData->fMinSize;
4747 }
4748 
4749 
4750 BSize
4751 BView::ExplicitMaxSize() const
4752 {
4753 	return fLayoutData->fMaxSize;
4754 }
4755 
4756 
4757 BSize
4758 BView::ExplicitPreferredSize() const
4759 {
4760 	return fLayoutData->fPreferredSize;
4761 }
4762 
4763 
4764 BAlignment
4765 BView::ExplicitAlignment() const
4766 {
4767 	return fLayoutData->fAlignment;
4768 }
4769 
4770 
4771 bool
4772 BView::HasHeightForWidth()
4773 {
4774 	return (fLayoutData->fLayout
4775 		? fLayoutData->fLayout->HasHeightForWidth() : false);
4776 }
4777 
4778 
4779 void
4780 BView::GetHeightForWidth(float width, float* min, float* max, float* preferred)
4781 {
4782 	if (fLayoutData->fLayout)
4783 		fLayoutData->fLayout->GetHeightForWidth(width, min, max, preferred);
4784 }
4785 
4786 
4787 void
4788 BView::SetLayout(BLayout* layout)
4789 {
4790 	if (layout == fLayoutData->fLayout)
4791 		return;
4792 
4793 	if (layout && layout->Layout())
4794 		debugger("BView::SetLayout() failed, layout is already in use.");
4795 
4796 	fFlags |= B_SUPPORTS_LAYOUT;
4797 
4798 	// unset and delete the old layout
4799 	if (fLayoutData->fLayout) {
4800 		fLayoutData->fLayout->SetOwner(NULL);
4801 		delete fLayoutData->fLayout;
4802 	}
4803 
4804 	fLayoutData->fLayout = layout;
4805 
4806 	if (fLayoutData->fLayout) {
4807 		fLayoutData->fLayout->SetOwner(this);
4808 
4809 		// add all children
4810 		int count = CountChildren();
4811 		for (int i = 0; i < count; i++)
4812 			fLayoutData->fLayout->AddView(ChildAt(i));
4813 	}
4814 
4815 	InvalidateLayout();
4816 }
4817 
4818 
4819 BLayout*
4820 BView::GetLayout() const
4821 {
4822 	return fLayoutData->fLayout;
4823 }
4824 
4825 
4826 void
4827 BView::InvalidateLayout(bool descendants)
4828 {
4829 	// printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
4830 	//	this, descendants, fLayoutData->fLayoutValid,
4831 	//	fLayoutData->fLayoutInProgress);
4832 
4833 	if (!fLayoutData->fMinMaxValid || fLayoutData->fLayoutInProgress
4834  			|| fLayoutData->fLayoutInvalidationDisabled > 0) {
4835 		return;
4836 	}
4837 
4838 	fLayoutData->fLayoutValid = false;
4839 	fLayoutData->fMinMaxValid = false;
4840 	LayoutInvalidated(descendants);
4841 
4842 	if (descendants) {
4843 		for (BView* child = fFirstChild;
4844 			child; child = child->fNextSibling) {
4845 			child->InvalidateLayout(descendants);
4846 		}
4847 	}
4848 
4849 	if (fLayoutData->fLayout)
4850 		fLayoutData->fLayout->InvalidateLayout(descendants);
4851 	else
4852 		_InvalidateParentLayout();
4853 
4854 	if (fTopLevelView && fOwner)
4855 		fOwner->PostMessage(B_LAYOUT_WINDOW);
4856 }
4857 
4858 
4859 void
4860 BView::EnableLayoutInvalidation()
4861 {
4862 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
4863 		fLayoutData->fLayoutInvalidationDisabled--;
4864 }
4865 
4866 
4867 void
4868 BView::DisableLayoutInvalidation()
4869 {
4870 	fLayoutData->fLayoutInvalidationDisabled++;
4871 }
4872 
4873 
4874 bool
4875 BView::IsLayoutInvalidationDisabled()
4876 {
4877 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
4878 		return true;
4879 	return false;
4880 }
4881 
4882 
4883 bool
4884 BView::IsLayoutValid() const
4885 {
4886 	return fLayoutData->fLayoutValid;
4887 }
4888 
4889 
4890 void
4891 BView::ResetLayoutInvalidation()
4892 {
4893 	fLayoutData->fMinMaxValid = true;
4894 }
4895 
4896 
4897 BLayoutContext*
4898 BView::LayoutContext() const
4899 {
4900 	return fLayoutData->fLayoutContext;
4901 }
4902 
4903 
4904 void
4905 BView::Layout(bool force)
4906 {
4907 	BLayoutContext context;
4908 	_Layout(force, &context);
4909 }
4910 
4911 
4912 void
4913 BView::Relayout()
4914 {
4915 	if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) {
4916 		fLayoutData->fNeedsRelayout = true;
4917 		if (fLayoutData->fLayout)
4918 			fLayoutData->fLayout->RequireLayout();
4919 
4920 		// Layout() is recursive, that is if the parent view is currently laid
4921 		// out, we don't call layout() on this view, but wait for the parent's
4922 		// Layout() to do that for us.
4923 		if (!fParent || !fParent->fLayoutData->fLayoutInProgress)
4924 			Layout(false);
4925 	}
4926 }
4927 
4928 
4929 void
4930 BView::LayoutInvalidated(bool descendants)
4931 {
4932 	// hook method
4933 }
4934 
4935 
4936 void
4937 BView::DoLayout()
4938 {
4939 	if (fLayoutData->fLayout)
4940 		fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
4941 }
4942 
4943 
4944 void
4945 BView::SetToolTip(const char* text)
4946 {
4947 	if (text == NULL || text[0] == '\0') {
4948 		SetToolTip((BToolTip*)NULL);
4949 		return;
4950 	}
4951 
4952 	if (BTextToolTip* tip = dynamic_cast<BTextToolTip*>(fToolTip))
4953 		tip->SetText(text);
4954 	else
4955 		SetToolTip(new BTextToolTip(text));
4956 }
4957 
4958 
4959 void
4960 BView::SetToolTip(BToolTip* tip)
4961 {
4962 	if (fToolTip == tip)
4963 		return;
4964 	else if (tip == NULL)
4965 		HideToolTip();
4966 
4967 	if (fToolTip != NULL)
4968 		fToolTip->ReleaseReference();
4969 
4970 	fToolTip = tip;
4971 
4972 	if (fToolTip != NULL)
4973 		fToolTip->AcquireReference();
4974 }
4975 
4976 
4977 BToolTip*
4978 BView::ToolTip() const
4979 {
4980 	return fToolTip;
4981 }
4982 
4983 
4984 void
4985 BView::ShowToolTip(BToolTip* tip)
4986 {
4987 	if (tip == NULL)
4988 		return;
4989 
4990 	BPoint where;
4991 	GetMouse(&where, NULL, false);
4992 
4993 	BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where), this);
4994 }
4995 
4996 
4997 void
4998 BView::HideToolTip()
4999 {
5000 	BToolTipManager::Manager()->HideTip();
5001 }
5002 
5003 
5004 bool
5005 BView::GetToolTipAt(BPoint point, BToolTip** _tip)
5006 {
5007 	if (fToolTip != NULL) {
5008 		*_tip = fToolTip;
5009 		return true;
5010 	}
5011 
5012 	*_tip = NULL;
5013 	return false;
5014 }
5015 
5016 
5017 void
5018 BView::LayoutChanged()
5019 {
5020 	// hook method
5021 }
5022 
5023 
5024 void
5025 BView::_Layout(bool force, BLayoutContext* context)
5026 {
5027 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context);
5028 //printf("  fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n",
5029 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid,
5030 //fLayoutData->fLayoutInProgress);
5031 	if (fLayoutData->fNeedsRelayout || !fLayoutData->fLayoutValid || force) {
5032 		fLayoutData->fLayoutValid = false;
5033 
5034 		if (fLayoutData->fLayoutInProgress)
5035 			return;
5036 
5037 		BLayoutContext* oldContext = fLayoutData->fLayoutContext;
5038 		fLayoutData->fLayoutContext = context;
5039 
5040 		fLayoutData->fLayoutInProgress = true;
5041 		DoLayout();
5042 		fLayoutData->fLayoutInProgress = false;
5043 
5044 		fLayoutData->fLayoutValid = true;
5045 		fLayoutData->fMinMaxValid = true;
5046 		fLayoutData->fNeedsRelayout = false;
5047 
5048 		// layout children
5049 		for(BView* child = fFirstChild; child; child = child->fNextSibling) {
5050 			if (!child->IsHidden(child))
5051 				child->_Layout(force, context);
5052 		}
5053 
5054 		LayoutChanged();
5055 
5056 		fLayoutData->fLayoutContext = oldContext;
5057 
5058 		// invalidate the drawn content, if requested
5059 		if (fFlags & B_INVALIDATE_AFTER_LAYOUT)
5060 			Invalidate();
5061 	}
5062 }
5063 
5064 
5065 void
5066 BView::_LayoutLeft(BLayout* deleted)
5067 {
5068 	// If our layout is added to another layout (via BLayout::AddItem())
5069 	// then we share ownership of our layout. In the event that our layout gets
5070 	// deleted by the layout it has been added to, this method is called so
5071 	// that we don't double-delete our layout.
5072 	if (fLayoutData->fLayout == deleted)
5073 		fLayoutData->fLayout = NULL;
5074 	InvalidateLayout();
5075 }
5076 
5077 
5078 void
5079 BView::_InvalidateParentLayout()
5080 {
5081 	if (!fParent)
5082 		return;
5083 
5084 	BLayout* layout = fLayoutData->fLayout;
5085 	BLayout* layoutParent = layout ? layout->Layout() : NULL;
5086 	if (layoutParent) {
5087 		layoutParent->InvalidateLayout();
5088 	} else if (fLayoutData->fLayoutItems.CountItems() > 0) {
5089 		int32 count = fLayoutData->fLayoutItems.CountItems();
5090 		for (int32 i = 0; i < count; i++) {
5091 			fLayoutData->fLayoutItems.ItemAt(i)->Layout()->InvalidateLayout();
5092 		}
5093 	} else {
5094 		fParent->InvalidateLayout();
5095 	}
5096 }
5097 
5098 
5099 //	#pragma mark - Private Functions
5100 
5101 
5102 void
5103 BView::_InitData(BRect frame, const char* name, uint32 resizingMode,
5104 	uint32 flags)
5105 {
5106 	// Info: The name of the view is set by BHandler constructor
5107 
5108 	STRACE(("BView::_InitData: enter\n"));
5109 
5110 	// initialize members
5111 	if ((resizingMode & ~_RESIZE_MASK_) || (flags & _RESIZE_MASK_))
5112 		printf("%s BView::_InitData(): resizing mode or flags swapped\n", name);
5113 
5114 	// There are applications that swap the resize mask and the flags in the
5115 	// BView constructor. This does not cause problems under BeOS as it just
5116 	// ors the two fields to one 32bit flag.
5117 	// For now we do the same but print the above warning message.
5118 	// TODO: this should be removed at some point and the original
5119 	// version restored:
5120 	// fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
5121 	fFlags = resizingMode | flags;
5122 
5123 	// handle rounding
5124 	frame.left = roundf(frame.left);
5125 	frame.top = roundf(frame.top);
5126 	frame.right = roundf(frame.right);
5127 	frame.bottom = roundf(frame.bottom);
5128 
5129 	fParentOffset.Set(frame.left, frame.top);
5130 
5131 	fOwner = NULL;
5132 	fParent = NULL;
5133 	fNextSibling = NULL;
5134 	fPreviousSibling = NULL;
5135 	fFirstChild = NULL;
5136 
5137 	fShowLevel = 0;
5138 	fTopLevelView = false;
5139 
5140 	fCurrentPicture = NULL;
5141 	fCommArray = NULL;
5142 
5143 	fVerScroller = NULL;
5144 	fHorScroller = NULL;
5145 
5146 	fIsPrinting = false;
5147 	fAttached = false;
5148 
5149 	// TODO: Since we cannot communicate failure, we don't use std::nothrow here
5150 	// TODO: Maybe we could auto-delete those views on AddChild() instead?
5151 	fState = new BPrivate::ViewState;
5152 
5153 	fBounds = frame.OffsetToCopy(B_ORIGIN);
5154 	fShelf = NULL;
5155 
5156 	fEventMask = 0;
5157 	fEventOptions = 0;
5158 	fMouseEventOptions = 0;
5159 
5160 	fLayoutData = new LayoutData;
5161 
5162 	fToolTip = NULL;
5163 }
5164 
5165 
5166 void
5167 BView::_RemoveCommArray()
5168 {
5169 	if (fCommArray) {
5170 		delete [] fCommArray->array;
5171 		delete fCommArray;
5172 		fCommArray = NULL;
5173 	}
5174 }
5175 
5176 
5177 void
5178 BView::_SetOwner(BWindow* newOwner)
5179 {
5180 	if (!newOwner)
5181 		_RemoveCommArray();
5182 
5183 	if (fOwner != newOwner && fOwner) {
5184 		if (fOwner->fFocus == this)
5185 			MakeFocus(false);
5186 
5187 		if (fOwner->fLastMouseMovedView == this)
5188 			fOwner->fLastMouseMovedView = NULL;
5189 
5190 		fOwner->RemoveHandler(this);
5191 		if (fShelf)
5192 			fOwner->RemoveHandler(fShelf);
5193 	}
5194 
5195 	if (newOwner && newOwner != fOwner) {
5196 		newOwner->AddHandler(this);
5197 		if (fShelf)
5198 			newOwner->AddHandler(fShelf);
5199 
5200 		if (fTopLevelView)
5201 			SetNextHandler(newOwner);
5202 		else
5203 			SetNextHandler(fParent);
5204 	}
5205 
5206 	fOwner = newOwner;
5207 
5208 	for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling)
5209 		child->_SetOwner(newOwner);
5210 }
5211 
5212 
5213 void
5214 BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
5215 {
5216 	if (!_CheckOwnerLockAndSwitchCurrent())
5217 		return;
5218 
5219 	if (picture == NULL) {
5220 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5221 		fOwner->fLink->Attach<int32>(-1);
5222 
5223 		// NOTE: No need to sync here, since the -1 token cannot
5224 		// become invalid on the server.
5225 	} else {
5226 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5227 		fOwner->fLink->Attach<int32>(picture->Token());
5228 		fOwner->fLink->Attach<BPoint>(where);
5229 		fOwner->fLink->Attach<bool>(invert);
5230 
5231 		// NOTE: "sync" defaults to true in public methods. If you know what
5232 		// you are doing, i.e. if you know your BPicture stays valid, you
5233 		// can avoid the performance impact of syncing. In a use-case where
5234 		// the client creates BPictures on the stack, these BPictures may
5235 		// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
5236 		// goes out of scope, and the command is processed earlier in the
5237 		// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
5238 		// ServerWindow thread, which will then have the result that no
5239 		// ServerPicture is found of the token.
5240 		if (sync)
5241 			Sync();
5242 	}
5243 }
5244 
5245 
5246 bool
5247 BView::_RemoveChildFromList(BView* child)
5248 {
5249 	if (child->fParent != this)
5250 		return false;
5251 
5252 	if (fFirstChild == child) {
5253 		// it's the first view in the list
5254 		fFirstChild = child->fNextSibling;
5255 	} else {
5256 		// there must be a previous sibling
5257 		child->fPreviousSibling->fNextSibling = child->fNextSibling;
5258 	}
5259 
5260 	if (child->fNextSibling)
5261 		child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
5262 
5263 	child->fParent = NULL;
5264 	child->fNextSibling = NULL;
5265 	child->fPreviousSibling = NULL;
5266 
5267 	return true;
5268 }
5269 
5270 
5271 bool
5272 BView::_AddChildToList(BView* child, BView* before)
5273 {
5274 	if (!child)
5275 		return false;
5276 	if (child->fParent != NULL) {
5277 		debugger("View already belongs to someone else");
5278 		return false;
5279 	}
5280 	if (before != NULL && before->fParent != this) {
5281 		debugger("Invalid before view");
5282 		return false;
5283 	}
5284 
5285 	if (before != NULL) {
5286 		// add view before this one
5287 		child->fNextSibling = before;
5288 		child->fPreviousSibling = before->fPreviousSibling;
5289 		if (child->fPreviousSibling != NULL)
5290 			child->fPreviousSibling->fNextSibling = child;
5291 
5292 		before->fPreviousSibling = child;
5293 		if (fFirstChild == before)
5294 			fFirstChild = child;
5295 	} else {
5296 		// add view to the end of the list
5297 		BView* last = fFirstChild;
5298 		while (last != NULL && last->fNextSibling != NULL) {
5299 			last = last->fNextSibling;
5300 		}
5301 
5302 		if (last != NULL) {
5303 			last->fNextSibling = child;
5304 			child->fPreviousSibling = last;
5305 		} else {
5306 			fFirstChild = child;
5307 			child->fPreviousSibling = NULL;
5308 		}
5309 
5310 		child->fNextSibling = NULL;
5311 	}
5312 
5313 	child->fParent = this;
5314 	return true;
5315 }
5316 
5317 
5318 /*!	\brief Creates the server counterpart of this view.
5319 	This is only done for views that are part of the view hierarchy, ie. when
5320 	they are attached to a window.
5321 	RemoveSelf() deletes the server object again.
5322 */
5323 bool
5324 BView::_CreateSelf()
5325 {
5326 	// AS_VIEW_CREATE & AS_VIEW_CREATE_ROOT do not use the
5327 	// current view mechanism via _CheckLockAndSwitchCurrent() - the token
5328 	// of the view and its parent are both send to the server.
5329 
5330 	if (fTopLevelView)
5331 		fOwner->fLink->StartMessage(AS_VIEW_CREATE_ROOT);
5332 	else
5333  		fOwner->fLink->StartMessage(AS_VIEW_CREATE);
5334 
5335 	fOwner->fLink->Attach<int32>(_get_object_token_(this));
5336 	fOwner->fLink->AttachString(Name());
5337 	fOwner->fLink->Attach<BRect>(Frame());
5338 	fOwner->fLink->Attach<BPoint>(LeftTop());
5339 	fOwner->fLink->Attach<uint32>(ResizingMode());
5340 	fOwner->fLink->Attach<uint32>(fEventMask);
5341 	fOwner->fLink->Attach<uint32>(fEventOptions);
5342 	fOwner->fLink->Attach<uint32>(Flags());
5343 	fOwner->fLink->Attach<bool>(IsHidden(this));
5344 	fOwner->fLink->Attach<rgb_color>(fState->view_color);
5345 	if (fTopLevelView)
5346 		fOwner->fLink->Attach<int32>(B_NULL_TOKEN);
5347 	else
5348 		fOwner->fLink->Attach<int32>(_get_object_token_(fParent));
5349 	fOwner->fLink->Flush();
5350 
5351 	_CheckOwnerLockAndSwitchCurrent();
5352 	fState->UpdateServerState(*fOwner->fLink);
5353 
5354 	// we create all its children, too
5355 
5356 	for (BView* child = fFirstChild; child != NULL;
5357 			child = child->fNextSibling) {
5358 		child->_CreateSelf();
5359 	}
5360 
5361 	fOwner->fLink->Flush();
5362 	return true;
5363 }
5364 
5365 
5366 /*!	Sets the new view position.
5367 	It doesn't contact the server, though - the only case where this
5368 	is called outside of MoveTo() is as reaction of moving a view
5369 	in the server (a.k.a. B_WINDOW_RESIZED).
5370 	It also calls the BView's FrameMoved() hook.
5371 */
5372 void
5373 BView::_MoveTo(int32 x, int32 y)
5374 {
5375 	fParentOffset.Set(x, y);
5376 
5377 	if (Window() != NULL && fFlags & B_FRAME_EVENTS) {
5378 		BMessage moved(B_VIEW_MOVED);
5379 		moved.AddInt64("when", system_time());
5380 		moved.AddPoint("where", BPoint(x, y));
5381 
5382 		BMessenger target(this);
5383 		target.SendMessage(&moved);
5384 	}
5385 }
5386 
5387 
5388 /*!	Computes the actual new frame size and recalculates the size of
5389 	the children as well.
5390 	It doesn't contact the server, though - the only case where this
5391 	is called outside of ResizeBy() is as reaction of resizing a view
5392 	in the server (a.k.a. B_WINDOW_RESIZED).
5393 	It also calls the BView's FrameResized() hook.
5394 */
5395 void
5396 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight)
5397 {
5398 	fBounds.right += deltaWidth;
5399 	fBounds.bottom += deltaHeight;
5400 
5401 	if (Window() == NULL) {
5402 		// we're not supposed to exercise the resizing code in case
5403 		// we haven't been attached to a window yet
5404 		return;
5405 	}
5406 
5407 	// layout the children
5408 	if (fFlags & B_SUPPORTS_LAYOUT) {
5409 		Relayout();
5410 	} else {
5411 		for (BView* child = fFirstChild; child; child = child->fNextSibling)
5412 			child->_ParentResizedBy(deltaWidth, deltaHeight);
5413 	}
5414 
5415 	if (fFlags & B_FRAME_EVENTS) {
5416 		BMessage resized(B_VIEW_RESIZED);
5417 		resized.AddInt64("when", system_time());
5418 		resized.AddInt32("width", fBounds.IntegerWidth());
5419 		resized.AddInt32("height", fBounds.IntegerHeight());
5420 
5421 		BMessenger target(this);
5422 		target.SendMessage(&resized);
5423 	}
5424 }
5425 
5426 
5427 /*!	Relayouts the view according to its resizing mode. */
5428 void
5429 BView::_ParentResizedBy(int32 x, int32 y)
5430 {
5431 	uint32 resizingMode = fFlags & _RESIZE_MASK_;
5432 	BRect newFrame = Frame();
5433 
5434 	// follow with left side
5435 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
5436 		newFrame.left += x;
5437 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
5438 		newFrame.left += x / 2;
5439 
5440 	// follow with right side
5441 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
5442 		newFrame.right += x;
5443 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
5444 		newFrame.right += x / 2;
5445 
5446 	// follow with top side
5447 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
5448 		newFrame.top += y;
5449 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
5450 		newFrame.top += y / 2;
5451 
5452 	// follow with bottom side
5453 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
5454 		newFrame.bottom += y;
5455 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
5456 		newFrame.bottom += y / 2;
5457 
5458 	if (newFrame.LeftTop() != fParentOffset) {
5459 		// move view
5460 		_MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top));
5461 	}
5462 
5463 	if (newFrame != Frame()) {
5464 		// resize view
5465 		int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width());
5466 		int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height());
5467 		_ResizeBy(widthDiff, heightDiff);
5468 	}
5469 }
5470 
5471 
5472 void
5473 BView::_Activate(bool active)
5474 {
5475 	WindowActivated(active);
5476 
5477 	for (BView* child = fFirstChild; child != NULL;
5478 			child = child->fNextSibling) {
5479 		child->_Activate(active);
5480 	}
5481 }
5482 
5483 
5484 void
5485 BView::_Attach()
5486 {
5487 	AttachedToWindow();
5488 	fAttached = true;
5489 
5490 	// after giving the view a chance to do this itself,
5491 	// check for the B_PULSE_NEEDED flag and make sure the
5492 	// window set's up the pulse messaging
5493 	if (fOwner) {
5494 		if (fFlags & B_PULSE_NEEDED) {
5495 			_CheckLock();
5496 			if (fOwner->fPulseRunner == NULL)
5497 				fOwner->SetPulseRate(fOwner->PulseRate());
5498 		}
5499 
5500 		if (!fOwner->IsHidden())
5501 			Invalidate();
5502 	}
5503 
5504 	for (BView* child = fFirstChild; child != NULL;
5505 			child = child->fNextSibling) {
5506 		// we need to check for fAttached as new views could have been
5507 		// added in AttachedToWindow() - and those are already attached
5508 		if (!child->fAttached)
5509 			child->_Attach();
5510 	}
5511 
5512 	AllAttached();
5513 }
5514 
5515 
5516 void
5517 BView::_Detach()
5518 {
5519 	DetachedFromWindow();
5520 	fAttached = false;
5521 
5522 	for (BView* child = fFirstChild; child != NULL;
5523 			child = child->fNextSibling) {
5524 		child->_Detach();
5525 	}
5526 
5527 	AllDetached();
5528 
5529 	if (fOwner) {
5530 		_CheckLock();
5531 
5532 		if (!fOwner->IsHidden())
5533 			Invalidate();
5534 
5535 		// make sure our owner doesn't need us anymore
5536 
5537 		if (fOwner->CurrentFocus() == this) {
5538 			MakeFocus(false);
5539 			// MakeFocus() is virtual and might not be
5540 			// passing through to the BView version,
5541 			// but we need to make sure at this point
5542 			// that we are not the focus view anymore.
5543 			if (fOwner->CurrentFocus() == this)
5544 				fOwner->_SetFocus(NULL, true);
5545 		}
5546 
5547 		if (fOwner->fDefaultButton == this)
5548 			fOwner->SetDefaultButton(NULL);
5549 
5550 		if (fOwner->fKeyMenuBar == this)
5551 			fOwner->fKeyMenuBar = NULL;
5552 
5553 		if (fOwner->fLastMouseMovedView == this)
5554 			fOwner->fLastMouseMovedView = NULL;
5555 
5556 		if (fOwner->fLastViewToken == _get_object_token_(this))
5557 			fOwner->fLastViewToken = B_NULL_TOKEN;
5558 
5559 		_SetOwner(NULL);
5560 	}
5561 }
5562 
5563 
5564 void
5565 BView::_Draw(BRect updateRect)
5566 {
5567 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW))
5568 		return;
5569 
5570 	// NOTE: if ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW
5571 	// -> View is simply not drawn at all
5572 
5573 	_SwitchServerCurrentView();
5574 
5575 	ConvertFromScreen(&updateRect);
5576 
5577 	// TODO: make states robust (the hook implementation could
5578 	// mess things up if it uses non-matching Push- and PopState(),
5579 	// we would not be guaranteed to still have the same state on
5580 	// the stack after having called Draw())
5581 	PushState();
5582 	Draw(updateRect);
5583 	PopState();
5584 	Flush();
5585 }
5586 
5587 
5588 void
5589 BView::_DrawAfterChildren(BRect updateRect)
5590 {
5591 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW)
5592 		|| !(Flags() & B_DRAW_ON_CHILDREN))
5593 		return;
5594 
5595 	_SwitchServerCurrentView();
5596 
5597 	ConvertFromScreen(&updateRect);
5598 
5599 	// TODO: make states robust (see above)
5600 	PushState();
5601 	DrawAfterChildren(updateRect);
5602 	PopState();
5603 	Flush();
5604 }
5605 
5606 
5607 void
5608 BView::_Pulse()
5609 {
5610 	if ((Flags() & B_PULSE_NEEDED) != 0)
5611 		Pulse();
5612 
5613 	for (BView* child = fFirstChild; child != NULL;
5614 			child = child->fNextSibling) {
5615 		child->_Pulse();
5616 	}
5617 }
5618 
5619 
5620 void
5621 BView::_UpdateStateForRemove()
5622 {
5623 	// TODO: _CheckLockAndSwitchCurrent() would be good enough, no?
5624 	if (!_CheckOwnerLockAndSwitchCurrent())
5625 		return;
5626 
5627 	fState->UpdateFrom(*fOwner->fLink);
5628 //	if (!fState->IsValid(B_VIEW_FRAME_BIT)) {
5629 //		fOwner->fLink->StartMessage(AS_VIEW_GET_COORD);
5630 //
5631 //		status_t code;
5632 //		if (fOwner->fLink->FlushWithReply(code) == B_OK
5633 //			&& code == B_OK) {
5634 //			fOwner->fLink->Read<BPoint>(&fParentOffset);
5635 //			fOwner->fLink->Read<BRect>(&fBounds);
5636 //			fState->valid_flags |= B_VIEW_FRAME_BIT;
5637 //		}
5638 //	}
5639 
5640 	// update children as well
5641 
5642 	for (BView* child = fFirstChild; child != NULL;
5643 			child = child->fNextSibling) {
5644 		if (child->fOwner)
5645 			child->_UpdateStateForRemove();
5646 	}
5647 }
5648 
5649 
5650 inline void
5651 BView::_UpdatePattern(::pattern pattern)
5652 {
5653 	if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern)
5654 		return;
5655 
5656 	if (fOwner) {
5657 		_CheckLockAndSwitchCurrent();
5658 
5659 		fOwner->fLink->StartMessage(AS_VIEW_SET_PATTERN);
5660 		fOwner->fLink->Attach< ::pattern>(pattern);
5661 
5662 		fState->valid_flags |= B_VIEW_PATTERN_BIT;
5663 	}
5664 
5665 	fState->pattern = pattern;
5666 }
5667 
5668 
5669 void
5670 BView::_FlushIfNotInTransaction()
5671 {
5672 	if (!fOwner->fInTransaction) {
5673 		fOwner->Flush();
5674 	}
5675 }
5676 
5677 
5678 BShelf*
5679 BView::_Shelf() const
5680 {
5681 	return fShelf;
5682 }
5683 
5684 
5685 void
5686 BView::_SetShelf(BShelf* shelf)
5687 {
5688 	if (fShelf != NULL && fOwner != NULL)
5689 		fOwner->RemoveHandler(fShelf);
5690 
5691 	fShelf = shelf;
5692 
5693 	if (fShelf != NULL && fOwner != NULL)
5694 		fOwner->AddHandler(fShelf);
5695 }
5696 
5697 
5698 status_t
5699 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
5700 	uint32 followFlags, uint32 options)
5701 {
5702 	if (!_CheckOwnerLockAndSwitchCurrent())
5703 		return B_ERROR;
5704 
5705 	int32 serverToken = bitmap ? bitmap->_ServerToken() : -1;
5706 
5707 	fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_BITMAP);
5708 	fOwner->fLink->Attach<int32>(serverToken);
5709 	fOwner->fLink->Attach<BRect>(srcRect);
5710 	fOwner->fLink->Attach<BRect>(dstRect);
5711 	fOwner->fLink->Attach<int32>(followFlags);
5712 	fOwner->fLink->Attach<int32>(options);
5713 
5714 	status_t status = B_ERROR;
5715 	fOwner->fLink->FlushWithReply(status);
5716 
5717 	return status;
5718 }
5719 
5720 
5721 bool
5722 BView::_CheckOwnerLockAndSwitchCurrent() const
5723 {
5724 	STRACE(("BView(%s)::_CheckOwnerLockAndSwitchCurrent()\n", Name()));
5725 
5726 	if (fOwner == NULL) {
5727 		debugger("View method requires owner and doesn't have one.");
5728 		return false;
5729 	}
5730 
5731 	_CheckLockAndSwitchCurrent();
5732 
5733 	return true;
5734 }
5735 
5736 
5737 bool
5738 BView::_CheckOwnerLock() const
5739 {
5740 	if (fOwner) {
5741 		fOwner->check_lock();
5742 		return true;
5743 	} else {
5744 		debugger("View method requires owner and doesn't have one.");
5745 		return false;
5746 	}
5747 }
5748 
5749 
5750 void
5751 BView::_CheckLockAndSwitchCurrent() const
5752 {
5753 	STRACE(("BView(%s)::_CheckLockAndSwitchCurrent()\n", Name()));
5754 
5755 	if (!fOwner)
5756 		return;
5757 
5758 	fOwner->check_lock();
5759 
5760 	_SwitchServerCurrentView();
5761 }
5762 
5763 
5764 void
5765 BView::_CheckLock() const
5766 {
5767 	if (fOwner)
5768 		fOwner->check_lock();
5769 }
5770 
5771 
5772 void
5773 BView::_SwitchServerCurrentView() const
5774 {
5775 	int32 serverToken = _get_object_token_(this);
5776 
5777 	if (fOwner->fLastViewToken != serverToken) {
5778 		STRACE(("contacting app_server... sending token: %ld\n", serverToken));
5779 		fOwner->fLink->StartMessage(AS_SET_CURRENT_VIEW);
5780 		fOwner->fLink->Attach<int32>(serverToken);
5781 
5782 		fOwner->fLastViewToken = serverToken;
5783 	}
5784 }
5785 
5786 
5787 status_t
5788 BView::ScrollWithMouseWheelDelta(BScrollBar* scrollBar, float delta)
5789 {
5790 	if (scrollBar == NULL || delta == 0.0f)
5791 		return B_BAD_VALUE;
5792 
5793 	float smallStep;
5794 	float largeStep;
5795 	scrollBar->GetSteps(&smallStep, &largeStep);
5796 
5797 	// pressing the shift key scrolls faster (following the pseudo-standard set
5798 	// by other desktop environments).
5799 	if ((modifiers() & B_SHIFT_KEY) != 0)
5800 		delta *= largeStep;
5801 	else
5802 		delta *= smallStep * 3;
5803 
5804 	scrollBar->SetValue(scrollBar->Value() + delta);
5805 
5806 	return B_OK;
5807 }
5808 
5809 
5810 #if __GNUC__ == 2
5811 
5812 
5813 extern "C" void
5814 _ReservedView1__5BView(BView* view, BRect rect)
5815 {
5816 	view->BView::DrawAfterChildren(rect);
5817 }
5818 
5819 
5820 extern "C" void
5821 _ReservedView2__5BView(BView* view)
5822 {
5823 	// MinSize()
5824 	perform_data_min_size data;
5825 	view->Perform(PERFORM_CODE_MIN_SIZE, &data);
5826 }
5827 
5828 
5829 extern "C" void
5830 _ReservedView3__5BView(BView* view)
5831 {
5832 	// MaxSize()
5833 	perform_data_max_size data;
5834 	view->Perform(PERFORM_CODE_MAX_SIZE, &data);
5835 }
5836 
5837 
5838 extern "C" BSize
5839 _ReservedView4__5BView(BView* view)
5840 {
5841 	// PreferredSize()
5842 	perform_data_preferred_size data;
5843 	view->Perform(PERFORM_CODE_PREFERRED_SIZE, &data);
5844 	return data.return_value;
5845 }
5846 
5847 
5848 extern "C" BAlignment
5849 _ReservedView5__5BView(BView* view)
5850 {
5851 	// LayoutAlignment()
5852 	perform_data_layout_alignment data;
5853 	view->Perform(PERFORM_CODE_LAYOUT_ALIGNMENT, &data);
5854 	return data.return_value;
5855 }
5856 
5857 
5858 extern "C" bool
5859 _ReservedView6__5BView(BView* view)
5860 {
5861 	// HasHeightForWidth()
5862 	perform_data_has_height_for_width data;
5863 	view->Perform(PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH, &data);
5864 	return data.return_value;
5865 }
5866 
5867 
5868 extern "C" void
5869 _ReservedView7__5BView(BView* view, float width, float* min, float* max,
5870 	float* preferred)
5871 {
5872 	// GetHeightForWidth()
5873 	perform_data_get_height_for_width data;
5874 	data.width = width;
5875 	view->Perform(PERFORM_CODE_GET_HEIGHT_FOR_WIDTH, &data);
5876 	if (min != NULL)
5877 		*min = data.min;
5878 	if (max != NULL)
5879 		*max = data.max;
5880 	if (preferred != NULL)
5881 		*preferred = data.preferred;
5882 }
5883 
5884 
5885 extern "C" void
5886 _ReservedView8__5BView(BView* view, BLayout* layout)
5887 {
5888 	// SetLayout()
5889 	perform_data_set_layout data;
5890 	data.layout = layout;
5891 	view->Perform(PERFORM_CODE_SET_LAYOUT, &data);
5892 }
5893 
5894 
5895 extern "C" void
5896 _ReservedView9__5BView(BView* view, bool descendants)
5897 {
5898 	// LayoutInvalidated()
5899 	perform_data_layout_invalidated data;
5900 	data.descendants = descendants;
5901 	view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
5902 }
5903 
5904 
5905 extern "C" void
5906 _ReservedView10__5BView(BView* view)
5907 {
5908 	// DoLayout()
5909 	view->Perform(PERFORM_CODE_DO_LAYOUT, NULL);
5910 }
5911 
5912 
5913 #endif	// __GNUC__ == 2
5914 
5915 
5916 extern "C" bool
5917 B_IF_GCC_2(_ReservedView11__5BView, _ZN5BView15_ReservedView11Ev)(
5918 	BView* view, BPoint point, BToolTip** _toolTip)
5919 {
5920 	// GetToolTipAt()
5921 	perform_data_get_tool_tip_at data;
5922 	data.point = point;
5923 	data.tool_tip = _toolTip;
5924 	view->Perform(PERFORM_CODE_GET_TOOL_TIP_AT, &data);
5925 	return data.return_value;
5926 }
5927 
5928 
5929 extern "C" void
5930 B_IF_GCC_2(_ReservedView12__5BView, _ZN5BView15_ReservedView12Ev)(
5931 	BView* view)
5932 {
5933 	// LayoutChanged();
5934 	view->Perform(PERFORM_CODE_LAYOUT_CHANGED, NULL);
5935 }
5936 
5937 
5938 void BView::_ReservedView13() {}
5939 void BView::_ReservedView14() {}
5940 void BView::_ReservedView15() {}
5941 void BView::_ReservedView16() {}
5942 
5943 
5944 BView::BView(const BView& other)
5945 	:
5946 	BHandler()
5947 {
5948 	// this is private and not functional, but exported
5949 }
5950 
5951 
5952 BView&
5953 BView::operator=(const BView& other)
5954 {
5955 	// this is private and not functional, but exported
5956 	return *this;
5957 }
5958 
5959 
5960 void
5961 BView::_PrintToStream()
5962 {
5963 	printf("BView::_PrintToStream()\n");
5964 	printf("\tName: %s\n"
5965 		"\tParent: %s\n"
5966 		"\tFirstChild: %s\n"
5967 		"\tNextSibling: %s\n"
5968 		"\tPrevSibling: %s\n"
5969 		"\tOwner(Window): %s\n"
5970 		"\tToken: %" B_PRId32 "\n"
5971 		"\tFlags: %" B_PRId32 "\n"
5972 		"\tView origin: (%f,%f)\n"
5973 		"\tView Bounds rectangle: (%f,%f,%f,%f)\n"
5974 		"\tShow level: %d\n"
5975 		"\tTopView?: %s\n"
5976 		"\tBPicture: %s\n"
5977 		"\tVertical Scrollbar %s\n"
5978 		"\tHorizontal Scrollbar %s\n"
5979 		"\tIs Printing?: %s\n"
5980 		"\tShelf?: %s\n"
5981 		"\tEventMask: %" B_PRId32 "\n"
5982 		"\tEventOptions: %" B_PRId32 "\n",
5983 	Name(),
5984 	fParent ? fParent->Name() : "NULL",
5985 	fFirstChild ? fFirstChild->Name() : "NULL",
5986 	fNextSibling ? fNextSibling->Name() : "NULL",
5987 	fPreviousSibling ? fPreviousSibling->Name() : "NULL",
5988 	fOwner ? fOwner->Name() : "NULL",
5989 	_get_object_token_(this),
5990 	fFlags,
5991 	fParentOffset.x, fParentOffset.y,
5992 	fBounds.left, fBounds.top, fBounds.right, fBounds.bottom,
5993 	fShowLevel,
5994 	fTopLevelView ? "YES" : "NO",
5995 	fCurrentPicture? "YES" : "NULL",
5996 	fVerScroller? "YES" : "NULL",
5997 	fHorScroller? "YES" : "NULL",
5998 	fIsPrinting? "YES" : "NO",
5999 	fShelf? "YES" : "NO",
6000 	fEventMask,
6001 	fEventOptions);
6002 
6003 	printf("\tState status:\n"
6004 		"\t\tLocalCoordianteSystem: (%f,%f)\n"
6005 		"\t\tPenLocation: (%f,%f)\n"
6006 		"\t\tPenSize: %f\n"
6007 		"\t\tHighColor: [%d,%d,%d,%d]\n"
6008 		"\t\tLowColor: [%d,%d,%d,%d]\n"
6009 		"\t\tViewColor: [%d,%d,%d,%d]\n"
6010 		"\t\tPattern: %" B_PRIx64 "\n"
6011 		"\t\tDrawingMode: %d\n"
6012 		"\t\tLineJoinMode: %d\n"
6013 		"\t\tLineCapMode: %d\n"
6014 		"\t\tMiterLimit: %f\n"
6015 		"\t\tAlphaSource: %d\n"
6016 		"\t\tAlphaFuntion: %d\n"
6017 		"\t\tScale: %f\n"
6018 		"\t\t(Print)FontAliasing: %s\n"
6019 		"\t\tFont Info:\n",
6020 	fState->origin.x, fState->origin.y,
6021 	fState->pen_location.x, fState->pen_location.y,
6022 	fState->pen_size,
6023 	fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha,
6024 	fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha,
6025 	fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha,
6026 	*((uint64*)&(fState->pattern)),
6027 	fState->drawing_mode,
6028 	fState->line_join,
6029 	fState->line_cap,
6030 	fState->miter_limit,
6031 	fState->alpha_source_mode,
6032 	fState->alpha_function_mode,
6033 	fState->scale,
6034 	fState->font_aliasing? "YES" : "NO");
6035 
6036 	fState->font.PrintToStream();
6037 
6038 	// TODO: also print the line array.
6039 }
6040 
6041 
6042 void
6043 BView::_PrintTree()
6044 {
6045 	int32 spaces = 2;
6046 	BView* c = fFirstChild; //c = short for: current
6047 	printf( "'%s'\n", Name() );
6048 	if (c != NULL) {
6049 		while(true) {
6050 			// action block
6051 			{
6052 				for (int i = 0; i < spaces; i++)
6053 					printf(" ");
6054 
6055 				printf( "'%s'\n", c->Name() );
6056 			}
6057 
6058 			// go deep
6059 			if (c->fFirstChild) {
6060 				c = c->fFirstChild;
6061 				spaces += 2;
6062 			} else {
6063 				// go right
6064 				if (c->fNextSibling) {
6065 					c = c->fNextSibling;
6066 				} else {
6067 					// go up
6068 					while (!c->fParent->fNextSibling && c->fParent != this) {
6069 						c = c->fParent;
6070 						spaces -= 2;
6071 					}
6072 
6073 					// that enough! We've reached this view.
6074 					if (c->fParent == this)
6075 						break;
6076 
6077 					c = c->fParent->fNextSibling;
6078 					spaces -= 2;
6079 				}
6080 			}
6081 		}
6082 	}
6083 }
6084 
6085 
6086 // #pragma mark -
6087 
6088 
6089 BLayoutItem*
6090 BView::Private::LayoutItemAt(int32 index)
6091 {
6092 	return fView->fLayoutData->fLayoutItems.ItemAt(index);
6093 }
6094 
6095 
6096 int32
6097 BView::Private::CountLayoutItems()
6098 {
6099 	return fView->fLayoutData->fLayoutItems.CountItems();
6100 }
6101 
6102 
6103 void
6104 BView::Private::RegisterLayoutItem(BLayoutItem* item)
6105 {
6106 	fView->fLayoutData->fLayoutItems.AddItem(item);
6107 }
6108 
6109 
6110 void
6111 BView::Private::DeregisterLayoutItem(BLayoutItem* item)
6112 {
6113 	fView->fLayoutData->fLayoutItems.RemoveItem(item);
6114 }
6115 
6116 
6117 bool
6118 BView::Private::MinMaxValid()
6119 {
6120 	return fView->fLayoutData->fMinMaxValid;
6121 }
6122 
6123 
6124 bool
6125 BView::Private::WillLayout()
6126 {
6127 	BView::LayoutData* data = fView->fLayoutData;
6128 	if (data->fLayoutInProgress)
6129 		return false;
6130 	if (data->fNeedsRelayout || !data->fLayoutValid || !data->fMinMaxValid)
6131 		return true;
6132 	return false;
6133 }
6134