xref: /haiku/src/kits/interface/View.cpp (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Adrian Oanca <adioanca@cotty.iren.ro>
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 #include <BeBuild.h>
12 #include <InterfaceDefs.h>
13 #include <PropertyInfo.h>
14 #include <Handler.h>
15 #include <View.h>
16 #include <Window.h>
17 #include <Message.h>
18 #include <MessageQueue.h>
19 #include <Rect.h>
20 #include <Point.h>
21 #include <Region.h>
22 #include <Font.h>
23 #include <ScrollBar.h>
24 #include <Cursor.h>
25 #include <Bitmap.h>
26 #include <Picture.h>
27 #include <Polygon.h>
28 #include <Shape.h>
29 #include <Button.h>
30 #include <Shelf.h>
31 #include <MenuBar.h>
32 #include <String.h>
33 #include <SupportDefs.h>
34 #include <Application.h>
35 
36 #include <AppMisc.h>
37 #include <ViewAux.h>
38 #include <TokenSpace.h>
39 #include <MessageUtils.h>
40 #include <ColorUtils.h>
41 #include <AppServerLink.h>
42 #include <PortLink.h>
43 #include <ServerProtocol.h>
44 
45 #ifdef USING_MESSAGE4
46 #include <MessagePrivate.h>
47 #endif
48 
49 #include <math.h>
50 #include <stdio.h>
51 
52 
53 //#define DEBUG_BVIEW
54 #ifdef DEBUG_BVIEW
55 #	include <stdio.h>
56 #	define STRACE(x) printf x
57 #	define BVTRACE PrintToStream()
58 #else
59 #	define STRACE(x) ;
60 #	define BVTRACE ;
61 #endif
62 
63 #define MAX_ATTACHMENT_SIZE 49152
64 
65 
66 static property_info sViewPropInfo[] = {
67 	{ "Frame", { B_GET_PROPERTY, 0 },
68 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the view's frame rectangle.",0 },
69 
70 	{ "Frame", { B_SET_PROPERTY, 0 },
71 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the view's frame rectangle.",0 },
72 
73 	{ "Hidden", { B_GET_PROPERTY, 0 },
74 		{ B_DIRECT_SPECIFIER, 0 }, "Returns true if the view is hidden; false otherwise.",0 },
75 
76 	{ "Hidden", { B_SET_PROPERTY, 0 },
77 		{ B_DIRECT_SPECIFIER, 0 }, "Hides or shows the view.",0 },
78 
79 	{ "Shelf", { 0 },
80 		{ B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the shelf.",0 },
81 
82 	{ "View", { B_COUNT_PROPERTIES, 0 },
83 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the number of of child views.",0 },
84 
85 	{ "View", { 0 },
86 		{ B_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 },
87 
88 	{ "View", { 0 },
89 		{ B_REVERSE_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 },
90 
91 	{ "View", { 0 },
92 		{ B_NAME_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 },
93 
94 	{ 0, { 0 }, { 0 }, 0, 0 }
95 };
96 
97 
98 // General Functions
99 //------------------------------------------------------------------------------
100 
101 
102 static inline uint32
103 get_uint32_color(rgb_color color)
104 {
105 	return *(uint32 *)&color;
106 }
107 
108 
109 static inline void
110 set_rgb_color(rgb_color &color, uint8 r, uint8 g, uint8 b, uint8 a = 255)
111 {
112 	color.red = r;
113 	color.green = g;
114 	color.blue = b;
115 	color.alpha = a;
116 }
117 
118 
119 //	#pragma mark -
120 
121 
122 namespace BPrivate {
123 
124 ViewState::ViewState()
125 {
126 	pen_location.Set(0, 0);
127 	pen_size = 1.0;
128 
129 	// This probably needs to be set to bounds by the owning BView
130 	clipping_region.MakeEmpty();
131 
132 	set_rgb_color(high_color, 0, 0, 0);
133 	set_rgb_color(low_color, 255, 255, 255);
134 	view_color = low_color;
135 
136 	pattern = B_SOLID_HIGH;
137 	drawing_mode = B_OP_COPY;
138 
139 	origin.Set(0, 0);
140 
141 	line_join = B_MITER_JOIN;
142 	line_cap = B_BUTT_CAP;
143 	miter_limit = B_DEFAULT_MITER_LIMIT;
144 
145 	alpha_source_mode = B_PIXEL_ALPHA;
146 	alpha_function_mode = B_ALPHA_OVERLAY;
147 
148 	scale = 1.0;
149 
150 	font = *be_plain_font;
151 	font_flags = font.Flags();
152 	font_aliasing = false;
153 
154 	/*
155 		INFO: We include(invalidate) only B_VIEW_CLIP_REGION_BIT flag
156 		because we should get the clipping region from app_server.
157 		The other flags do not need to be included because the data they
158 		represent is already in sync with app_server - app_server uses the
159 		same init(default) values.
160 	*/
161 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
162 
163 	archiving_flags = B_VIEW_FRAME_BIT;
164 }
165 
166 
167 void
168 ViewState::UpdateServerFontState(BPrivate::PortLink &link)
169 {
170 	link.StartMessage(AS_LAYER_SET_FONT_STATE);
171 	link.Attach<uint16>(font_flags);
172 
173 	// always present.
174 	if (font_flags & B_FONT_FAMILY_AND_STYLE) {
175 		uint32 fontID;
176 		fontID = font.FamilyAndStyle();
177 
178 		link.Attach<uint32>(fontID);
179 	}
180 
181 	if (font_flags & B_FONT_SIZE)
182 		link.Attach<float>(font.Size());
183 
184 	if (font_flags & B_FONT_SHEAR)
185 		link.Attach<float>(font.Shear());
186 
187 	if (font_flags & B_FONT_ROTATION)
188 		link.Attach<float>(font.Rotation());
189 
190 	if (font_flags & B_FONT_SPACING)
191 		link.Attach<uint8>(font.Spacing());
192 
193 	if (font_flags & B_FONT_ENCODING)
194 		link.Attach<uint8>(font.Encoding());
195 
196 	if (font_flags & B_FONT_FACE)
197 		link.Attach<uint16>(font.Face());
198 
199 	if (font_flags & B_FONT_FLAGS)
200 		link.Attach<uint32>(font.Flags());
201 }
202 
203 
204 void
205 ViewState::UpdateServerState(BPrivate::PortLink &link)
206 {
207 	UpdateServerFontState(link);
208 
209 	link.StartMessage(AS_LAYER_SET_STATE);
210 	link.Attach<BPoint>(pen_location);
211 	link.Attach<float>(pen_size);
212 	link.Attach<rgb_color>(high_color);
213 	link.Attach<rgb_color>(low_color);
214 	link.Attach< ::pattern>(pattern);
215 	link.Attach<int8>((int8)drawing_mode);
216 	link.Attach<BPoint>(origin);
217 	link.Attach<int8>((int8)line_join);
218 	link.Attach<int8>((int8)line_cap);
219 	link.Attach<float>(miter_limit);
220 	link.Attach<int8>((int8)alpha_source_mode);
221 	link.Attach<int8>((int8)alpha_function_mode);
222 	link.Attach<float>(scale);
223 	link.Attach<bool>(font_aliasing);
224 
225 	// we send the 'local' clipping region... if we have one...
226 	int32 count = clipping_region.CountRects();
227 
228 	link.Attach<int32>(count);
229 	for (int32 i = 0; i < count; i++)
230 		link.Attach<BRect>(clipping_region.RectAt(i));
231 
232 	//	Although we might have a 'local' clipping region, when we call
233 	//	BView::GetClippingRegion() we ask for the 'global' one and it
234 	//	is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag
235 
236 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
237 }
238 
239 
240 void
241 ViewState::UpdateFrom(BPrivate::PortLink &link)
242 {
243 	link.StartMessage(AS_LAYER_GET_STATE);
244 
245 	int32 code;
246 	if (link.FlushWithReply(code) != B_OK
247 		|| code != SERVER_TRUE)
248 		return;
249 
250 	uint32 fontID;
251 	float size;
252 	float shear;
253 	float rotation;
254 	uint8 spacing;
255 	uint8 encoding;
256 	uint16 face;
257 	uint32 flags;
258 
259 	// read and set the font state
260 	link.Read<int32>((int32 *)&fontID);
261 	link.Read<float>(&size);
262 	link.Read<float>(&shear);
263 	link.Read<float>(&rotation);
264 	link.Read<int8>((int8 *)&spacing);
265 	link.Read<int8>((int8 *)&encoding);
266 	link.Read<int16>((int16 *)&face);
267 	link.Read<int32>((int32 *)&flags);
268 
269 	font_flags = B_FONT_ALL;
270 	font.SetFamilyAndStyle(fontID);
271 	font.SetSize(size);
272 	font.SetShear(shear);
273 	font.SetRotation(rotation);
274 	font.SetSpacing(spacing);
275 	font.SetEncoding(encoding);
276 	font.SetFace(face);
277 	font.SetFlags(flags);
278 
279 	// read and set view's state
280 	link.Read<BPoint>(&pen_location);
281 	link.Read<float>(&pen_size);
282 	link.Read<rgb_color>(&high_color);
283 	link.Read<rgb_color>(&low_color);
284 	link.Read< ::pattern>(&pattern);
285 	link.Read<BPoint>(&origin);
286 
287 	int8 drawingMode;
288 	link.Read<int8>((int8 *)&drawingMode);
289 	drawing_mode = (::drawing_mode)drawingMode;
290 
291 	link.Read<int8>((int8 *)&line_cap);
292 	link.Read<int8>((int8 *)&line_join);
293 	link.Read<float>(&miter_limit);
294 	link.Read<int8>((int8 *)&alpha_source_mode);
295 	link.Read<int8>((int8 *)&alpha_function_mode);
296 	link.Read<float>(&scale);
297 	link.Read<bool>(&font_aliasing);
298 
299 	// no need to read the clipping region, as it's invalid
300 	// next time we need it anyway
301 
302 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
303 }
304 
305 }	// namespace BPrivate
306 
307 
308 //	#pragma mark -
309 
310 
311 BView::BView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
312 	: BHandler(name)
313 {
314 	InitData(frame, name, resizingMode, flags);
315 }
316 
317 
318 BView::BView(BMessage *archive)
319 	: BHandler(archive)
320 {
321 	uint32 resizingMode;
322 	uint32 flags;
323 	BRect frame;
324 
325 	archive->FindRect("_frame", &frame);
326 	if (archive->FindInt32("_resize_mode", (int32 *)&resizingMode) != B_OK)
327 		resizingMode = 0;
328 
329 	if (archive->FindInt32("_flags", (int32 *)&flags) != B_OK)
330 		flags = 0;
331 
332 	InitData(frame, Name(), resizingMode, flags);
333 
334 	font_family family;
335 	font_style style;
336 	if (archive->FindString("_fname", 0, (const char **)&family) == B_OK
337 		&& archive->FindString("_fname", 1, (const char **)&style) == B_OK) {
338 		BFont font;
339 		font.SetFamilyAndStyle(family, style);
340 
341 		float size;
342 		if (archive->FindFloat("_fflt", 0, &size) == B_OK)
343 			font.SetSize(size);
344 
345 		float shear;
346 		if (archive->FindFloat("_fflt", 1, &shear) == B_OK)
347 			font.SetShear(shear);
348 
349 		float rotation;
350 		if (archive->FindFloat("_fflt", 2, &rotation) == B_OK)
351 		 font.SetRotation(rotation);
352 
353 		SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE
354 			| B_FONT_SHEAR | B_FONT_ROTATION);
355 	}
356 
357 	rgb_color color;
358 	if (archive->FindInt32("_color", 0, (int32 *)&color) == B_OK)
359 		SetHighColor(color);
360 	if (archive->FindInt32("_color", 1, (int32 *)&color) == B_OK)
361 		SetLowColor(color);
362 	if (archive->FindInt32("_color", 2, (int32 *)&color) == B_OK)
363 		SetViewColor(color);
364 
365 	uint32 evMask;
366 	uint32 options;
367 	if (archive->FindInt32("_evmask", 0, (int32 *)&evMask) == B_OK
368 		&& archive->FindInt32("_evmask", 1, (int32 *)&options) == B_OK)
369 		SetEventMask(evMask, options);
370 
371 	BPoint origin;
372 	if (archive->FindPoint("_origin", &origin) == B_OK)
373 		SetOrigin(origin);
374 
375 	float penSize;
376 	if (archive->FindFloat("_psize", &penSize) == B_OK)
377 		SetPenSize(penSize);
378 
379 	BPoint penLocation;
380 	if ( archive->FindPoint("_ploc", &penLocation) == B_OK )
381 		MovePenTo( penLocation );
382 
383 	int16 lineCap;
384 	int16 lineJoin;
385 	float lineMiter;
386 	if (archive->FindInt16("_lmcapjoin", 0, &lineCap) == B_OK
387 		&& archive->FindInt16("_lmcapjoin", 1, &lineJoin) == B_OK
388 		&& archive->FindFloat("_lmmiter", &lineMiter) == B_OK)
389 		SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter);
390 
391 	int16 alphaBlend;
392 	int16 modeBlend;
393 	if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK
394 		&& archive->FindInt16("_blend", 1, &modeBlend) == B_OK)
395 		SetBlendingMode( (source_alpha)alphaBlend, (alpha_function)modeBlend);
396 
397 	uint32 drawingMode;
398 	if (archive->FindInt32("_dmod", (int32 *)&drawingMode) == B_OK)
399 		SetDrawingMode((drawing_mode)drawingMode);
400 
401 	BMessage msg;
402 	int32 i = 0;
403 	while (archive->FindMessage("_views", i++, &msg) == B_OK) {
404 		BArchivable *object = instantiate_object(&msg);
405 		BView *child = dynamic_cast<BView *>(object);
406 		if (child)
407 			AddChild(child);
408 	}
409 }
410 
411 
412 BArchivable *
413 BView::Instantiate(BMessage *data)
414 {
415 	if (!validate_instantiation(data , "BView"))
416 		return NULL;
417 
418 	return new BView(data);
419 }
420 
421 
422 status_t
423 BView::Archive(BMessage *data, bool deep) const
424 {
425 	status_t retval = BHandler::Archive(data, deep);
426 	if (retval != B_OK)
427 		return retval;
428 
429 	if (fState->archiving_flags & B_VIEW_FRAME_BIT)
430 		data->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset));
431 
432 	if (fState->archiving_flags & B_VIEW_RESIZE_BIT)
433 		data->AddInt32("_resize_mode", ResizingMode());
434 
435 	if (fState->archiving_flags & B_VIEW_FLAGS_BIT)
436 		data->AddInt32("_flags", Flags());
437 
438 	if (fState->archiving_flags & B_VIEW_EVENT_MASK_BIT) {
439 		data->AddInt32("_evmask", fEventMask);
440 		data->AddInt32("_evmask", fEventOptions);
441 	}
442 
443 	if (fState->archiving_flags & B_VIEW_FONT_BIT) {
444 		BFont font;
445 		GetFont(&font);
446 
447 		font_family family;
448 		font_style style;
449 		font.GetFamilyAndStyle(&family, &style);
450 		data->AddString("_fname", family);
451 		data->AddString("_fname", style);
452 
453 		data->AddFloat("_fflt", font.Size());
454 		data->AddFloat("_fflt", font.Shear());
455 		data->AddFloat("_fflt", font.Rotation());
456 	}
457 
458 	// colors
459 
460 	if (fState->archiving_flags & B_VIEW_HIGH_COLOR_BIT)
461 		data->AddInt32("_color", get_uint32_color(HighColor()));
462 
463 	if (fState->archiving_flags & B_VIEW_LOW_COLOR_BIT)
464 		data->AddInt32("_color", get_uint32_color(LowColor()));
465 
466 	if (fState->archiving_flags & B_VIEW_VIEW_COLOR_BIT)
467 		data->AddInt32("_color", get_uint32_color(ViewColor()));
468 
469 //	NOTE: we do not use this flag any more
470 //	if ( 1 ){
471 //		data->AddInt32("_dbuf", 1);
472 //	}
473 
474 	if (fState->archiving_flags & B_VIEW_ORIGIN_BIT)
475 		data->AddPoint("_origin", Origin());
476 
477 	if (fState->archiving_flags & B_VIEW_PEN_SIZE_BIT)
478 		data->AddFloat("_psize", PenSize());
479 
480 	if (fState->archiving_flags & B_VIEW_PEN_LOCATION_BIT)
481 		data->AddPoint("_ploc", PenLocation());
482 
483 	if (fState->archiving_flags & B_VIEW_LINE_MODES_BIT) {
484 		data->AddInt16("_lmcapjoin", (int16)LineCapMode());
485 		data->AddInt16("_lmcapjoin", (int16)LineJoinMode());
486 		data->AddFloat("_lmmiter", LineMiterLimit());
487 	}
488 
489 	if (fState->archiving_flags & B_VIEW_BLENDING_BIT) {
490 		source_alpha alphaSourceMode;
491 		alpha_function alphaFunctionMode;
492 		GetBlendingMode(&alphaSourceMode, &alphaFunctionMode);
493 
494 		data->AddInt16("_blend", (int16)alphaSourceMode);
495 		data->AddInt16("_blend", (int16)alphaFunctionMode);
496 	}
497 
498 	if (fState->archiving_flags & B_VIEW_DRAWING_MODE_BIT)
499 		data->AddInt32("_dmod", DrawingMode());
500 
501 	if (deep) {
502 		int32 i = 0;
503 		BView *child;
504 
505 		while ((child = ChildAt(i++)) != NULL) {
506 			BMessage childArchive;
507 
508 			retval = child->Archive(&childArchive, deep);
509 			if (retval == B_OK)
510 				data->AddMessage("_views", &childArchive);
511 		}
512 	}
513 
514 	return retval;
515 }
516 
517 
518 BView::~BView()
519 {
520 	STRACE(("BView(%s)::~BView()\n", this->Name()));
521 
522 	if (fOwner)
523 		debugger("Trying to delete a view that belongs to a window. Call RemoveSelf first.");
524 
525 	RemoveSelf();
526 
527 	// TODO: see about BShelf! must I delete it here? is it deleted by the window?
528 
529 	// we also delete all its childern
530 
531 	BView *child = fFirstChild;
532 	while (child) {
533 		BView *nextChild = child->fNextSibling;
534 
535 		deleteView(child);
536 		child = nextChild;
537 	}
538 
539 	if (fVerScroller)
540 		fVerScroller->SetTarget((BView *)NULL);
541 
542 	if (fHorScroller)
543 		fHorScroller->SetTarget((BView *)NULL);
544 
545 	SetName(NULL);
546 
547 	delete fPermanentState;
548 	delete fState;
549 	free(pr_state);
550 }
551 
552 
553 BRect
554 BView::Bounds() const
555 {
556 	// do we need to update our bounds?
557 	if (!fState->IsValid(B_VIEW_FRAME_BIT) && fOwner) {
558 		check_lock();
559 
560 		fOwner->fLink->StartMessage(AS_LAYER_GET_COORD);
561 
562 		int32 code;
563 		if (fOwner->fLink->FlushWithReply(code) == B_OK
564 			&& code == SERVER_TRUE) {
565 			fOwner->fLink->Read<BPoint>(const_cast<BPoint *>(&fParentOffset));
566 			fOwner->fLink->Read<BRect>(const_cast<BRect *>(&fBounds));
567 			fState->valid_flags |= B_VIEW_FRAME_BIT;
568 		}
569 	}
570 
571 	return fBounds;
572 }
573 
574 
575 void
576 BView::ConvertToParent(BPoint *point) const
577 {
578 	if (!fParent)
579 		return;
580 
581 	check_lock_no_pick();
582 
583 	// TODO: handle scale
584 
585 	// our local coordinate transformation
586 	*point -= Origin();
587 
588 	// our bounds location within the parent
589 	*point += fParentOffset;
590 }
591 
592 
593 BPoint
594 BView::ConvertToParent(BPoint point) const
595 {
596 	ConvertToParent(&point);
597 
598 	return point;
599 }
600 
601 
602 void
603 BView::ConvertFromParent(BPoint *point) const
604 {
605 	if (!fParent)
606 		return;
607 
608 	check_lock_no_pick();
609 
610 	// TODO: handle scale
611 
612 	// our bounds location within the parent
613 	*point -= fParentOffset;
614 
615 	// our local coordinate transformation
616 	*point += Origin();
617 }
618 
619 
620 BPoint
621 BView::ConvertFromParent(BPoint point) const
622 {
623 	ConvertFromParent(&point);
624 
625 	return point;
626 }
627 
628 
629 void
630 BView::ConvertToParent(BRect *rect) const
631 {
632 	if (!fParent)
633 		return;
634 
635 	check_lock_no_pick();
636 
637 	// TODO: handle scale
638 
639 	BPoint origin = Origin();
640 
641 	// our local coordinate transformation
642 	rect->OffsetBy(-origin.x, -origin.y);
643 
644 	// our bounds location within the parent
645 	rect->OffsetBy(fParentOffset);
646 }
647 
648 
649 BRect
650 BView::ConvertToParent(BRect rect) const
651 {
652 	ConvertToParent(&rect);
653 
654 	return rect;
655 }
656 
657 
658 void
659 BView::ConvertFromParent(BRect *rect) const
660 {
661 	if (!fParent)
662 		return;
663 
664 	check_lock_no_pick();
665 
666 	// TODO: handle scale
667 
668 	// our bounds location within the parent
669 	rect->OffsetBy(-fParentOffset.x, -fParentOffset.y);
670 
671 	// our local coordinate transformation
672 	rect->OffsetBy(Origin());
673 }
674 
675 
676 BRect
677 BView::ConvertFromParent(BRect rect) const
678 {
679 	ConvertFromParent(&rect);
680 
681 	return rect;
682 }
683 
684 
685 void
686 BView::ConvertToScreen(BPoint *pt) const
687 {
688 	if (!fParent) {
689 		if (fOwner)
690 			fOwner->ConvertToScreen(pt);
691 
692 		return;
693 	}
694 
695 	do_owner_check_no_pick();
696 
697 	ConvertToParent(pt);
698 	fParent->ConvertToScreen(pt);
699 }
700 
701 
702 BPoint
703 BView::ConvertToScreen(BPoint pt) const
704 {
705 	ConvertToScreen(&pt);
706 
707 	return pt;
708 }
709 
710 
711 void
712 BView::ConvertFromScreen(BPoint *pt) const
713 {
714 	if (!fParent) {
715 		if (fOwner)
716 			fOwner->ConvertFromScreen(pt);
717 
718 		return;
719 	}
720 
721 	do_owner_check_no_pick();
722 
723 	ConvertFromParent(pt);
724 	fParent->ConvertFromScreen(pt);
725 }
726 
727 
728 BPoint
729 BView::ConvertFromScreen(BPoint pt) const
730 {
731 	ConvertFromScreen(&pt);
732 
733 	return pt;
734 }
735 
736 
737 void
738 BView::ConvertToScreen(BRect *rect) const
739 {
740 	if (!fParent) {
741 		if (fOwner)
742 			fOwner->ConvertToScreen(rect);
743 
744 		return;
745 	}
746 
747 	do_owner_check_no_pick();
748 
749 	ConvertToParent(rect);
750 	fParent->ConvertToScreen(rect);
751 }
752 
753 
754 BRect
755 BView::ConvertToScreen(BRect rect) const
756 {
757 	ConvertToScreen(&rect);
758 
759 	return rect;
760 }
761 
762 
763 void
764 BView::ConvertFromScreen(BRect *rect) const
765 {
766 	if (!fParent) {
767 		if (fOwner)
768 			fOwner->ConvertFromScreen(rect);
769 
770 		return;
771 	}
772 
773 	do_owner_check_no_pick();
774 
775 	ConvertFromParent(rect);
776 	fParent->ConvertFromScreen(rect);
777 }
778 
779 
780 BRect
781 BView::ConvertFromScreen(BRect rect) const
782 {
783 	ConvertFromScreen(&rect);
784 
785 	return rect;
786 }
787 
788 
789 uint32
790 BView::Flags() const
791 {
792 	check_lock_no_pick();
793 	return fFlags & ~_RESIZE_MASK_;
794 }
795 
796 
797 void
798 BView::SetFlags(uint32 flags)
799 {
800 	if (Flags() == flags)
801 		return;
802 
803 	if (fOwner) {
804 		if (flags & B_PULSE_NEEDED) {
805 			check_lock_no_pick();
806 			if (!fOwner->fPulseEnabled)
807 				fOwner->SetPulseRate(500000);
808 		}
809 
810 		if (flags & (B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
811 					| B_FRAME_EVENTS | B_SUBPIXEL_PRECISE)) {
812 			check_lock();
813 
814 			fOwner->fLink->StartMessage(AS_LAYER_SET_FLAGS);
815 			fOwner->fLink->Attach<uint32>(flags);
816 		}
817 	}
818 
819 	/* Some useful info:
820 		fFlags is a unsigned long (32 bits)
821 		* bits 1-16 are used for BView's flags
822 		* bits 17-32 are used for BView' resize mask
823 		* _RESIZE_MASK_ is used for that. Look into View.h to see how
824 			it's defined
825 	*/
826 	fFlags = (flags & ~_RESIZE_MASK_) | (fFlags & _RESIZE_MASK_);
827 
828 	fState->archiving_flags |= B_VIEW_FLAGS_BIT;
829 }
830 
831 
832 BRect
833 BView::Frame() const
834 {
835 	check_lock_no_pick();
836 
837 	return Bounds().OffsetToCopy(fParentOffset.x, fParentOffset.y);
838 }
839 
840 
841 void
842 BView::Hide()
843 {
844 	if (fOwner && fShowLevel == 0) {
845 		check_lock();
846 		fOwner->fLink->StartMessage(AS_LAYER_HIDE);
847 	}
848 	fShowLevel++;
849 }
850 
851 
852 void
853 BView::Show()
854 {
855 	fShowLevel--;
856 	if (fOwner && fShowLevel == 0) {
857 		check_lock();
858 		fOwner->fLink->StartMessage(AS_LAYER_SHOW);
859 	}
860 }
861 
862 
863 bool
864 BView::IsFocus() const
865 {
866 	if (fOwner) {
867 		check_lock_no_pick();
868 		return fOwner->CurrentFocus() == this;
869 	} else
870 		return false;
871 }
872 
873 
874 bool
875 BView::IsHidden(const BView *lookingFrom) const
876 {
877 	if (fShowLevel > 0)
878 		return true;
879 
880 	// may we be egocentric?
881 	if (lookingFrom == this)
882 		return false;
883 
884 	// we have the same visibility state as our
885 	// parent, if there is one
886 	if (fParent)
887 		return fParent->IsHidden(lookingFrom);
888 
889 	// if we're the top view, and we're interested
890 	// in the "global" view, we're inheriting the
891 	// state of the window's visibility
892 	if (fOwner && lookingFrom == NULL)
893 		return fOwner->IsHidden();
894 
895 	return false;
896 }
897 
898 
899 bool
900 BView::IsHidden() const
901 {
902 	return IsHidden(NULL);
903 }
904 
905 
906 bool
907 BView::IsPrinting() const
908 {
909 	return f_is_printing;
910 }
911 
912 
913 BPoint
914 BView::LeftTop() const
915 {
916 	return fParentOffset;
917 }
918 
919 
920 void
921 BView::SetOrigin(BPoint pt)
922 {
923 	SetOrigin(pt.x, pt.y);
924 }
925 
926 
927 void
928 BView::SetOrigin(float x, float y)
929 {
930 	if (fState->IsValid(B_VIEW_ORIGIN_BIT)
931 		&& x == fState->origin.x && y == fState->origin.y)
932 		return;
933 
934 	if (do_owner_check()) {
935 		fOwner->fLink->StartMessage(AS_LAYER_SET_ORIGIN);
936 		fOwner->fLink->Attach<float>(x);
937 		fOwner->fLink->Attach<float>(y);
938 
939 		fState->valid_flags |= B_VIEW_ORIGIN_BIT;
940 	}
941 
942 // TODO: Bounds() is effected by SetOrigin() (?),
943 // so should we set the COORD_BIT too?
944 
945 	// our local coord system origin has changed, so when archiving we'll add this too
946 	fState->archiving_flags |= B_VIEW_ORIGIN_BIT;
947 }
948 
949 
950 BPoint
951 BView::Origin() const
952 {
953 	if (!fState->IsValid(B_VIEW_ORIGIN_BIT)) {
954 		do_owner_check();
955 
956 		fOwner->fLink->StartMessage(AS_LAYER_GET_ORIGIN);
957 
958 		int32 code;
959 		if (fOwner->fLink->FlushWithReply(code) == B_OK
960 			&& code == SERVER_TRUE) {
961 			fOwner->fLink->Read<BPoint>(&fState->origin);
962 
963 			fState->valid_flags |= B_VIEW_ORIGIN_BIT;
964 		}
965 	}
966 
967 	return fState->origin;
968 }
969 
970 
971 void
972 BView::SetResizingMode(uint32 mode)
973 {
974 	if (fOwner) {
975 		check_lock();
976 
977 		fOwner->fLink->StartMessage(AS_LAYER_RESIZE_MODE);
978 		fOwner->fLink->Attach<uint32>(mode);
979 	}
980 
981 	// look at SetFlags() for more info on the below line
982 	fFlags = (fFlags & ~_RESIZE_MASK_) | (mode & _RESIZE_MASK_);
983 
984 	// our resize mode has changed, so when archiving we'll add this too
985 	fState->archiving_flags |= B_VIEW_RESIZE_BIT;
986 }
987 
988 
989 uint32
990 BView::ResizingMode() const
991 {
992 	return fFlags & _RESIZE_MASK_;
993 }
994 
995 
996 void
997 BView::SetViewCursor(const BCursor *cursor, bool sync)
998 {
999 	if (!cursor)
1000 		return;
1001 
1002 	if (!fOwner)
1003 		debugger("View method requires owner and doesn't have one");
1004 
1005 	check_lock();
1006 
1007 	fOwner->fLink->StartMessage(AS_LAYER_CURSOR);
1008 	fOwner->fLink->Attach<int32>(cursor->m_serverToken);
1009 
1010 	if (sync)
1011 		fOwner->fLink->Flush();
1012 }
1013 
1014 
1015 void
1016 BView::Flush(void) const
1017 {
1018 	if (fOwner)
1019 		fOwner->Flush();
1020 }
1021 
1022 
1023 void
1024 BView::Sync(void) const
1025 {
1026 	do_owner_check_no_pick();
1027 	if (fOwner)
1028 		fOwner->Sync();
1029 }
1030 
1031 
1032 BWindow *
1033 BView::Window() const
1034 {
1035 	return fOwner;
1036 }
1037 
1038 
1039 //	#pragma mark -
1040 // Hook Functions
1041 
1042 
1043 void
1044 BView::AttachedToWindow()
1045 {
1046 	// Hook function
1047 	STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name()));
1048 }
1049 
1050 
1051 void
1052 BView::AllAttached()
1053 {
1054 	// Hook function
1055 	STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name()));
1056 }
1057 
1058 
1059 void
1060 BView::DetachedFromWindow()
1061 {
1062 	// Hook function
1063 	STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name()));
1064 }
1065 
1066 
1067 void
1068 BView::AllDetached()
1069 {
1070 	// Hook function
1071 	STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name()));
1072 }
1073 
1074 
1075 void
1076 BView::Draw(BRect updateRect)
1077 {
1078 	// Hook function
1079 	STRACE(("\tHOOK: BView(%s)::Draw()\n", Name()));
1080 }
1081 
1082 
1083 void
1084 BView::DrawAfterChildren(BRect r)
1085 {
1086 	// HOOK function
1087 	STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name()));
1088 }
1089 
1090 
1091 void
1092 BView::FrameMoved(BPoint newPosition)
1093 {
1094 	// Hook function
1095 	STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name()));
1096 }
1097 
1098 
1099 void
1100 BView::FrameResized(float newWidth, float newHeight)
1101 {
1102 	// Hook function
1103 	STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name()));
1104 }
1105 
1106 
1107 void
1108 BView::GetPreferredSize(float* _width, float* _height)
1109 {
1110 	STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name()));
1111 
1112 	*_width = fBounds.Width();
1113 	*_height = fBounds.Height();
1114 }
1115 
1116 
1117 void
1118 BView::ResizeToPreferred()
1119 {
1120 	STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name()));
1121 
1122 	float width;
1123 	float height;
1124 	GetPreferredSize(&width, &height);
1125 
1126 	ResizeTo(width, height);
1127 }
1128 
1129 
1130 void
1131 BView::KeyDown(const char* bytes, int32 numBytes)
1132 {
1133 	// Hook function
1134 	STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name()));
1135 
1136 	if (Window())
1137 		Window()->_KeyboardNavigation();
1138 }
1139 
1140 
1141 void
1142 BView::KeyUp(const char* bytes, int32 numBytes)
1143 {
1144 	// Hook function
1145 	STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name()));
1146 }
1147 
1148 
1149 void
1150 BView::MouseDown(BPoint where)
1151 {
1152 	// Hook function
1153 	STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name()));
1154 }
1155 
1156 
1157 void
1158 BView::MouseUp(BPoint where)
1159 {
1160 	// Hook function
1161 	STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name()));
1162 }
1163 
1164 
1165 void
1166 BView::MouseMoved(BPoint where, uint32 code, const BMessage* a_message)
1167 {
1168 	// Hook function
1169 	STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name()));
1170 }
1171 
1172 
1173 void
1174 BView::Pulse()
1175 {
1176 	// Hook function
1177 	STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name()));
1178 }
1179 
1180 
1181 void
1182 BView::TargetedByScrollView(BScrollView* scroll_view)
1183 {
1184 	// Hook function
1185 	STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name()));
1186 }
1187 
1188 
1189 void
1190 BView::WindowActivated(bool state)
1191 {
1192 	// Hook function
1193 	STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name()));
1194 }
1195 
1196 
1197 //	#pragma mark -
1198 //	Input Functions
1199 
1200 
1201 void
1202 BView::BeginRectTracking(BRect startRect, uint32 style)
1203 {
1204 	if (do_owner_check()) {
1205 		fOwner->fLink->StartMessage(AS_LAYER_BEGIN_RECT_TRACK);
1206 		fOwner->fLink->Attach<BRect>(startRect);
1207 		fOwner->fLink->Attach<int32>(style);
1208 	}
1209 }
1210 
1211 
1212 void
1213 BView::EndRectTracking()
1214 {
1215 	if (do_owner_check())
1216 		fOwner->fLink->StartMessage(AS_LAYER_END_RECT_TRACK);
1217 }
1218 
1219 
1220 void
1221 BView::DragMessage(BMessage *message, BRect dragRect, BHandler *replyTo)
1222 {
1223 	if (!message || !dragRect.IsValid())
1224 		return;
1225 
1226 	if (replyTo == NULL)
1227 		replyTo = this;
1228 
1229 	if (replyTo->Looper() == NULL)
1230 		debugger("DragMessage: warning - the Handler needs a looper");
1231 
1232 	do_owner_check_no_pick();
1233 
1234 	BPoint offset;
1235 
1236 	if (!message->HasInt32("buttons")) {
1237 		BMessage *msg = fOwner->CurrentMessage();
1238 		uint32 buttons;
1239 
1240 		if (msg) {
1241 			if (msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) {
1242 				BPoint point;
1243 				GetMouse(&point, &buttons, false);
1244 			}
1245 
1246 			BPoint point;
1247 			if (msg->FindPoint("be:view_where", &point) == B_OK)
1248 				offset = point - dragRect.LeftTop();
1249 		} else {
1250 			BPoint point;
1251 			GetMouse(&point, &buttons, false);
1252 		}
1253 
1254 		message->AddInt32("buttons", buttons);
1255 	}
1256 
1257 #ifndef USING_MESSAGE4
1258 	_set_message_reply_(message, BMessenger(replyTo, replyTo->Looper()));
1259 #else
1260 	BMessage::Private(message).SetReply(BMessenger(replyTo, replyTo->Looper()));
1261 #endif
1262 
1263 	int32 bufferSize = message->FlattenedSize();
1264 	char *buffer = new char[bufferSize];
1265 	message->Flatten(buffer, bufferSize);
1266 
1267 	fOwner->fLink->StartMessage(AS_LAYER_DRAG_RECT);
1268 	fOwner->fLink->Attach<BRect>(dragRect);
1269 	fOwner->fLink->Attach<BPoint>(offset);
1270 	fOwner->fLink->Attach<int32>(bufferSize);
1271 	fOwner->fLink->Attach(buffer, bufferSize);
1272 	fOwner->fLink->Flush();
1273 
1274 	delete [] buffer;
1275 }
1276 
1277 
1278 void
1279 BView::DragMessage(BMessage *message, BBitmap *image, BPoint offset,
1280 	BHandler *replyTo)
1281 {
1282 	DragMessage(message, image, B_OP_COPY, offset, replyTo);
1283 }
1284 
1285 
1286 void
1287 BView::DragMessage(BMessage *message, BBitmap *image,
1288 	drawing_mode dragMode, BPoint offset, BHandler *replyTo)
1289 {
1290 	// ToDo: is this correct? Isn't \a image allowed to be NULL?
1291 	if (message == NULL || image == NULL)
1292 		return;
1293 
1294 	if (replyTo == NULL)
1295 		replyTo = this;
1296 
1297 	if (replyTo->Looper() == NULL)
1298 		debugger("DragMessage: warning - the Handler needs a looper");
1299 
1300 	do_owner_check_no_pick();
1301 
1302 	if (!message->HasInt32("buttons")) {
1303 		BMessage *msg = fOwner->CurrentMessage();
1304 		uint32 buttons;
1305 
1306 		if (msg == NULL || msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) {
1307 			BPoint point;
1308 			GetMouse(&point, &buttons, false);
1309 		}
1310 
1311 		message->AddInt32("buttons", buttons);
1312 	}
1313 
1314 #ifndef USING_MESSAGE4
1315 	_set_message_reply_(message, BMessenger(replyTo, replyTo->Looper()));
1316 #else
1317 	BMessage::Private(message).SetReply(BMessenger(replyTo, replyTo->Looper()));
1318 #endif
1319 
1320 	int32 bufferSize = message->FlattenedSize();
1321 	char *buffer = new char[bufferSize];
1322 	message->Flatten(buffer, bufferSize);
1323 
1324 	fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE);
1325 	fOwner->fLink->Attach<int32>(image->get_server_token());
1326 	fOwner->fLink->Attach<int32>((int32)dragMode);
1327 	fOwner->fLink->Attach<BPoint>(offset);
1328 	fOwner->fLink->Attach<int32>(bufferSize);
1329 	fOwner->fLink->Attach(buffer, bufferSize);
1330 
1331 	delete [] buffer;
1332 
1333 	// TODO: in app_server the bitmap refCount must be incremented
1334 	// WRITE this into specs!!!!
1335 
1336 	delete image;
1337 }
1338 
1339 
1340 void
1341 BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue)
1342 {
1343 	do_owner_check();
1344 
1345 	if (checkMessageQueue) {
1346 		BMessageQueue *queue = Window()->MessageQueue();
1347 		queue->Lock();
1348 
1349 		Window()->UpdateIfNeeded();
1350 
1351 		// Look out for mouse update messages
1352 
1353 		BMessage *msg;
1354 		for (int32 i = 0; (msg = queue->FindMessage(i)) != NULL; i++) {
1355 			switch (msg->what) {
1356 				case B_MOUSE_UP:
1357 				case B_MOUSE_DOWN:
1358 				case B_MOUSE_MOVED:
1359 				{
1360 					msg->FindPoint("where", location);
1361 					msg->FindInt32("buttons", (int32 *)buttons);
1362 
1363 					// ToDo: the "where" coordinates are screen coordinates
1364 					//	unlike R5 - this might break applications!
1365 					ConvertFromScreen(location);
1366 
1367 					queue->RemoveMessage(msg);
1368 					delete msg;
1369 
1370 					queue->Unlock();
1371 					return;
1372 				}
1373 			}
1374 		}
1375 		queue->Unlock();
1376 	}
1377 
1378 	// If no mouse update message has been found in the message queue,
1379 	// we get the current mouse location and buttons from the app_server
1380 
1381 	fOwner->fLink->StartMessage(AS_LAYER_GET_MOUSE_COORDS);
1382 
1383 	int32 code;
1384 	if (fOwner->fLink->FlushWithReply(code) == B_OK
1385 		&& code == SERVER_TRUE) {
1386 		fOwner->fLink->Read<BPoint>(location);
1387 		fOwner->fLink->Read<uint32>(buttons);
1388 
1389 		// TODO: See above comment about coordinates
1390 		ConvertFromScreen(location);
1391 	} else
1392 		buttons = 0;
1393 }
1394 
1395 
1396 void
1397 BView::MakeFocus(bool focusState)
1398 {
1399 	if (fOwner) {
1400 		// TODO: If this view has focus and focusState==false,
1401 		// will there really be no other view with focus? No
1402 		// cycling to the next one?
1403 		BView *focus = fOwner->CurrentFocus();
1404 		if (focusState) {
1405 			// Unfocus a previous focus view
1406 			if (focus && focus != this)
1407 				focus->MakeFocus(false);
1408 			// if we want to make this view the current focus view
1409 			fOwner->fFocus = this;
1410 			fOwner->SetPreferredHandler(this);
1411 		} else {
1412 			// we want to unfocus this view, but only if it actually has focus
1413 			if (focus == this) {
1414 				fOwner->fFocus = NULL;
1415 				fOwner->SetPreferredHandler(NULL);
1416 			}
1417 		}
1418 	}
1419 }
1420 
1421 
1422 BScrollBar *
1423 BView::ScrollBar(orientation posture) const
1424 {
1425 	switch (posture) {
1426 		case B_VERTICAL:
1427 			return fVerScroller;
1428 
1429 		case B_HORIZONTAL:
1430 			return fHorScroller;
1431 
1432 		default:
1433 			return NULL;
1434 	}
1435 }
1436 
1437 
1438 void
1439 BView::ScrollBy(float dh, float dv)
1440 {
1441 	// scrolling by fractional values is not supported, is it?
1442 	dh = roundf(dh);
1443 	dv = roundf(dv);
1444 
1445 	// no reason to process this further if no scroll is intended.
1446 	if (dh == 0 && dv == 0)
1447 		return;
1448 
1449 	check_lock();
1450 
1451 	// if we're attached to a window tell app_server about this change
1452 	if (fOwner) {
1453 		fOwner->fLink->StartMessage(AS_LAYER_SCROLL);
1454 		fOwner->fLink->Attach<float>(dh);
1455 		fOwner->fLink->Attach<float>(dv);
1456 
1457 		fOwner->fLink->Flush();
1458 
1459 		fState->valid_flags &= ~(B_VIEW_FRAME_BIT | B_VIEW_ORIGIN_BIT);
1460 	}
1461 
1462 	// we modify our bounds rectangle by dh/dv coord units hor/ver.
1463 	fBounds.OffsetBy(dh, dv);
1464 //	fState->coordSysOrigin += BPoint(dh, dv);
1465 
1466 	// then set the new values of the scrollbars
1467 	if (fHorScroller)
1468 		fHorScroller->SetValue(fBounds.left);
1469 	if (fVerScroller)
1470 		fVerScroller->SetValue(fBounds.top);
1471 }
1472 
1473 
1474 void
1475 BView::ScrollTo(BPoint where)
1476 {
1477 	ScrollBy(where.x - fBounds.left, where.y - fBounds.top);
1478 }
1479 
1480 
1481 status_t
1482 BView::SetEventMask(uint32 mask, uint32 options)
1483 {
1484 	if (fEventMask == mask && fEventOptions == options)
1485 		return B_ERROR;
1486 
1487 	fEventMask = mask | (fEventMask & 0xFFFF0000);
1488 	fEventOptions = options;
1489 
1490 	fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT;
1491 
1492 	if (fOwner) {
1493 		check_lock();
1494 
1495 		fOwner->fLink->StartMessage(AS_LAYER_SET_EVENT_MASK);
1496 		fOwner->fLink->Attach<uint32>(mask);
1497 		fOwner->fLink->Attach<uint32>(options);
1498 	}
1499 
1500 	return B_OK;
1501 }
1502 
1503 
1504 uint32
1505 BView::EventMask()
1506 {
1507 	return fEventMask;
1508 }
1509 
1510 
1511 status_t
1512 BView::SetMouseEventMask(uint32 mask, uint32 options)
1513 {
1514 //	fEventMask = (mask << 16) | (fEventMask & 0x0000FFFF);
1515 //	fEventOptions = (options << 16) | (options & 0x0000FFFF);
1516 
1517 	if (do_owner_check()
1518 		&& fOwner->CurrentMessage()
1519 		&& fOwner->CurrentMessage()->what == B_MOUSE_DOWN) {
1520 		fOwner->fLink->StartMessage(AS_LAYER_SET_MOUSE_EVENT_MASK);
1521 		fOwner->fLink->Attach<uint32>(mask);
1522 		fOwner->fLink->Attach<uint32>(options);
1523 
1524 		return B_OK;
1525 	}
1526 	return B_ERROR;
1527 }
1528 
1529 
1530 //	#pragma mark -
1531 //	Graphic State Functions
1532 
1533 
1534 void
1535 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit)
1536 {
1537 	if (fState->IsValid(B_VIEW_LINE_MODES_BIT)
1538 		&& lineCap == fState->line_cap && lineJoin == fState->line_join
1539 		&& miterLimit == fState->miter_limit)
1540 		return;
1541 
1542 	if (fOwner) {
1543 		check_lock();
1544 
1545 		fOwner->fLink->StartMessage(AS_LAYER_SET_LINE_MODE);
1546 		fOwner->fLink->Attach<int8>((int8)lineCap);
1547 		fOwner->fLink->Attach<int8>((int8)lineJoin);
1548 		fOwner->fLink->Attach<float>(miterLimit);
1549 
1550 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
1551 	}
1552 
1553 	fState->line_cap = lineCap;
1554 	fState->line_join = lineJoin;
1555 	fState->miter_limit = miterLimit;
1556 
1557 	fState->archiving_flags |= B_VIEW_LINE_MODES_BIT;
1558 }
1559 
1560 
1561 join_mode
1562 BView::LineJoinMode() const
1563 {
1564 	// This will update the current state, if necessary
1565 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
1566 		LineMiterLimit();
1567 
1568 	return fState->line_join;
1569 }
1570 
1571 
1572 cap_mode
1573 BView::LineCapMode() const
1574 {
1575 	// This will update the current state, if necessary
1576 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
1577 		LineMiterLimit();
1578 
1579 	return fState->line_cap;
1580 }
1581 
1582 
1583 float
1584 BView::LineMiterLimit() const
1585 {
1586 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) {
1587 		check_lock();
1588 
1589 		fOwner->fLink->StartMessage(AS_LAYER_GET_LINE_MODE);
1590 
1591 		int32 code;
1592 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1593 			&& code == SERVER_TRUE) {
1594 			int8 cap, join;
1595 			fOwner->fLink->Read<int8>((int8 *)&cap);
1596 			fOwner->fLink->Read<int8>((int8 *)&join);
1597 			fOwner->fLink->Read<float>(&fState->miter_limit);
1598 
1599 			fState->line_cap = (cap_mode)cap;
1600 			fState->line_join = (join_mode)join;
1601 		}
1602 
1603 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
1604 	}
1605 
1606 	return fState->miter_limit;
1607 }
1608 
1609 
1610 void
1611 BView::PushState()
1612 {
1613 	do_owner_check();
1614 
1615 	fOwner->fLink->StartMessage(AS_LAYER_PUSH_STATE);
1616 
1617 	// initialize origin and scale
1618 	fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT;
1619 	fState->scale = 1.0f;
1620 	fState->origin.Set(0, 0);
1621 }
1622 
1623 
1624 void
1625 BView::PopState()
1626 {
1627 	do_owner_check();
1628 
1629 	fOwner->fLink->StartMessage(AS_LAYER_POP_STATE);
1630 
1631 	// invalidate all flags (except those that are not part of pop/push)
1632 	fState->valid_flags = B_VIEW_VIEW_COLOR_BIT;
1633 }
1634 
1635 
1636 void
1637 BView::SetScale(float scale) const
1638 {
1639 	if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale)
1640 		return;
1641 
1642 	if (fOwner) {
1643 		check_lock();
1644 
1645 		fOwner->fLink->StartMessage(AS_LAYER_SET_SCALE);
1646 		fOwner->fLink->Attach<float>(scale);
1647 
1648 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1649 	}
1650 
1651 	fState->scale = scale;
1652 	fState->archiving_flags |= B_VIEW_SCALE_BIT;
1653 }
1654 
1655 
1656 float
1657 BView::Scale() const
1658 {
1659 	if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) {
1660 		check_lock();
1661 
1662 		fOwner->fLink->StartMessage(AS_LAYER_GET_SCALE);
1663 
1664  		int32 code;
1665 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1666 			&& code == SERVER_TRUE)
1667 			fOwner->fLink->Read<float>(&fState->scale);
1668 
1669 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1670 	}
1671 
1672 	return fState->scale;
1673 }
1674 
1675 
1676 void
1677 BView::SetDrawingMode(drawing_mode mode)
1678 {
1679 	if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT)
1680 		&& mode == fState->drawing_mode)
1681 		return;
1682 
1683 	if (fOwner) {
1684 		check_lock();
1685 
1686 		fOwner->fLink->StartMessage(AS_LAYER_SET_DRAW_MODE);
1687 		fOwner->fLink->Attach<int8>((int8)mode);
1688 
1689 		fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
1690 	}
1691 
1692 	fState->drawing_mode = mode;
1693 	fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT;
1694 }
1695 
1696 
1697 drawing_mode
1698 BView::DrawingMode() const
1699 {
1700 	if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) {
1701 		check_lock();
1702 
1703 		fOwner->fLink->StartMessage(AS_LAYER_GET_DRAW_MODE);
1704 
1705 		int32 code;
1706 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1707 			&& code == SERVER_TRUE) {
1708 			int8 drawingMode;
1709 			fOwner->fLink->Read<int8>(&drawingMode);
1710 
1711 			fState->drawing_mode = (drawing_mode)drawingMode;
1712 			fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
1713 		}
1714 	}
1715 
1716 	return fState->drawing_mode;
1717 }
1718 
1719 
1720 void
1721 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction)
1722 {
1723 	if (fState->IsValid(B_VIEW_BLENDING_BIT)
1724 		&& sourceAlpha == fState->alpha_source_mode
1725 		&& alphaFunction == fState->alpha_function_mode)
1726 		return;
1727 
1728 	if (fOwner) {
1729 		check_lock();
1730 
1731 		fOwner->fLink->StartMessage(AS_LAYER_SET_BLEND_MODE);
1732 		fOwner->fLink->Attach<int8>((int8)sourceAlpha);
1733 		fOwner->fLink->Attach<int8>((int8)alphaFunction);
1734 
1735 		fState->valid_flags |= B_VIEW_BLENDING_BIT;
1736 	}
1737 
1738 	fState->alpha_source_mode = sourceAlpha;
1739 	fState->alpha_function_mode = alphaFunction;
1740 
1741 	fState->archiving_flags |= B_VIEW_BLENDING_BIT;
1742 }
1743 
1744 
1745 void
1746 BView::GetBlendingMode(source_alpha *_sourceAlpha,
1747 	alpha_function *_alphaFunction) const
1748 {
1749 	if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) {
1750 		check_lock();
1751 
1752 		fOwner->fLink->StartMessage(AS_LAYER_GET_BLEND_MODE);
1753 
1754 		int32 code;
1755  		if (fOwner->fLink->FlushWithReply(code) == B_OK
1756  			&& code == SERVER_TRUE) {
1757 			int8 alphaSourceMode, alphaFunctionMode;
1758 			fOwner->fLink->Read<int8>(&alphaSourceMode);
1759 			fOwner->fLink->Read<int8>(&alphaFunctionMode);
1760 
1761 			fState->alpha_source_mode = (source_alpha)alphaSourceMode;
1762 			fState->alpha_function_mode = (alpha_function)alphaFunctionMode;
1763 
1764 			fState->valid_flags |= B_VIEW_BLENDING_BIT;
1765 		}
1766 	}
1767 
1768 	if (_sourceAlpha)
1769 		*_sourceAlpha = fState->alpha_source_mode;
1770 
1771 	if (_alphaFunction)
1772 		*_alphaFunction = fState->alpha_function_mode;
1773 }
1774 
1775 
1776 void
1777 BView::MovePenTo(BPoint point)
1778 {
1779 	MovePenTo(point.x, point.y);
1780 }
1781 
1782 
1783 void
1784 BView::MovePenTo(float x, float y)
1785 {
1786 	if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT)
1787 		&& x == fState->pen_location.x && y == fState->pen_location.y)
1788 		return;
1789 
1790 	if (fOwner) {
1791 		check_lock();
1792 
1793 		fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_LOC);
1794 		fOwner->fLink->Attach<float>(x);
1795 		fOwner->fLink->Attach<float>(y);
1796 
1797 		fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
1798 	}
1799 
1800 	fState->pen_location.x = x;
1801 	fState->pen_location.y = y;
1802 
1803 	fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT;
1804 }
1805 
1806 
1807 void
1808 BView::MovePenBy(float x, float y)
1809 {
1810 	// this will update the pen location if necessary
1811 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT))
1812 		PenLocation();
1813 
1814 	MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y);
1815 }
1816 
1817 
1818 BPoint
1819 BView::PenLocation() const
1820 {
1821 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) {
1822 		check_lock();
1823 
1824 		fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_LOC);
1825 
1826 		int32 code;
1827 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1828 			&& code == SERVER_TRUE) {
1829 			fOwner->fLink->Read<BPoint>(&fState->pen_location);
1830 
1831 			fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
1832 		}
1833 	}
1834 
1835 	return fState->pen_location;
1836 }
1837 
1838 
1839 void
1840 BView::SetPenSize(float size)
1841 {
1842 	if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size)
1843 		return;
1844 
1845 	if (fOwner) {
1846 		check_lock();
1847 
1848 		fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_SIZE);
1849 		fOwner->fLink->Attach<float>(size);
1850 
1851 		fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
1852 	}
1853 
1854 	fState->pen_size = size;
1855 	fState->archiving_flags	|= B_VIEW_PEN_SIZE_BIT;
1856 }
1857 
1858 
1859 float
1860 BView::PenSize() const
1861 {
1862 	if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) {
1863 		check_lock();
1864 
1865 		fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_SIZE);
1866 
1867 		int32 code;
1868 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1869 			&& code == SERVER_TRUE) {
1870 			fOwner->fLink->Read<float>(&fState->pen_size);
1871 
1872 			fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
1873 		}
1874 	}
1875 
1876 	return fState->pen_size;
1877 }
1878 
1879 
1880 void
1881 BView::SetHighColor(rgb_color color)
1882 {
1883 	// are we up-to-date already?
1884 	if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT)
1885 		&& fState->high_color == color)
1886 		return;
1887 
1888 	if (fOwner) {
1889 		check_lock();
1890 
1891 		fOwner->fLink->StartMessage(AS_LAYER_SET_HIGH_COLOR);
1892 		fOwner->fLink->Attach<rgb_color>(color);
1893 
1894 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
1895 	}
1896 
1897 	set_rgb_color(fState->high_color, color.red, color.green,
1898 		color.blue, color.alpha);
1899 
1900 	fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT;
1901 }
1902 
1903 
1904 rgb_color
1905 BView::HighColor() const
1906 {
1907 	if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) {
1908 		check_lock();
1909 
1910 		fOwner->fLink->StartMessage(AS_LAYER_GET_HIGH_COLOR);
1911 
1912 		int32 code;
1913 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1914 			&& code == SERVER_TRUE) {
1915 			fOwner->fLink->Read<rgb_color>(&fState->high_color);
1916 
1917 			fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
1918 		}
1919 	}
1920 
1921 	return fState->high_color;
1922 }
1923 
1924 
1925 void
1926 BView::SetLowColor(rgb_color color)
1927 {
1928 	if (fState->IsValid(B_VIEW_LOW_COLOR_BIT)
1929 		&& fState->low_color == color)
1930 		return;
1931 
1932 	if (fOwner) {
1933 		check_lock();
1934 
1935 		fOwner->fLink->StartMessage(AS_LAYER_SET_LOW_COLOR);
1936 		fOwner->fLink->Attach<rgb_color>(color);
1937 
1938 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
1939 	}
1940 
1941 	set_rgb_color(fState->low_color, color.red, color.green,
1942 		color.blue, color.alpha);
1943 
1944 	fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT;
1945 }
1946 
1947 
1948 rgb_color
1949 BView::LowColor() const
1950 {
1951 	if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) {
1952 		check_lock();
1953 
1954 		fOwner->fLink->StartMessage(AS_LAYER_GET_LOW_COLOR);
1955 
1956 		int32 code;
1957 		if (fOwner->fLink->FlushWithReply(code) == B_OK
1958 			&& code == SERVER_TRUE) {
1959 			fOwner->fLink->Read<rgb_color>(&fState->low_color);
1960 
1961 			fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
1962 		}
1963 	}
1964 
1965 	return fState->low_color;
1966 }
1967 
1968 
1969 void
1970 BView::SetViewColor(rgb_color color)
1971 {
1972 	if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fState->view_color == color)
1973 		return;
1974 
1975 	if (fOwner) {
1976 		check_lock();
1977 
1978 		fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_COLOR);
1979 		fOwner->fLink->Attach<rgb_color>(color);
1980 
1981 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
1982 	}
1983 
1984 	set_rgb_color(fState->view_color, color.red, color.green,
1985 		color.blue, color.alpha);
1986 
1987 	fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT;
1988 }
1989 
1990 
1991 rgb_color
1992 BView::ViewColor() const
1993 {
1994 	if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) {
1995 		check_lock();
1996 
1997 		fOwner->fLink->StartMessage(AS_LAYER_GET_VIEW_COLOR);
1998 
1999 		int32 code;
2000 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2001 			&& code == SERVER_TRUE) {
2002 			fOwner->fLink->Read<rgb_color>(&fState->view_color);
2003 
2004 			fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2005 		}
2006 	}
2007 
2008 	return fState->view_color;
2009 }
2010 
2011 
2012 void
2013 BView::ForceFontAliasing(bool enable)
2014 {
2015 	if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT) && enable == fState->font_aliasing)
2016 		return;
2017 
2018 	if (fOwner) {
2019 		check_lock();
2020 
2021 		fOwner->fLink->StartMessage(AS_LAYER_PRINT_ALIASING);
2022 		fOwner->fLink->Attach<bool>(enable);
2023 
2024 		fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT;
2025 	}
2026 
2027 	fState->font_aliasing = enable;
2028 	fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT;
2029 }
2030 
2031 
2032 void
2033 BView::SetFont(const BFont* font, uint32 mask)
2034 {
2035 	if (!font || mask == 0)
2036 		return;
2037 
2038 	if (mask == B_FONT_ALL) {
2039 		fState->font = *font;
2040 	} else {
2041 		// ToDo: move this into a BFont method
2042 		if (mask & B_FONT_FAMILY_AND_STYLE)
2043 			fState->font.SetFamilyAndStyle(font->FamilyAndStyle());
2044 
2045 		if (mask & B_FONT_SIZE)
2046 			fState->font.SetSize(font->Size());
2047 
2048 		if (mask & B_FONT_SHEAR)
2049 			fState->font.SetShear(font->Shear());
2050 
2051 		if (mask & B_FONT_ROTATION)
2052 			fState->font.SetRotation(font->Rotation());
2053 
2054 		if (mask & B_FONT_SPACING)
2055 			fState->font.SetSpacing(font->Spacing());
2056 
2057 		if (mask & B_FONT_ENCODING)
2058 			fState->font.SetEncoding(font->Encoding());
2059 
2060 		if (mask & B_FONT_FACE)
2061 			fState->font.SetFace(font->Face());
2062 
2063 		if (mask & B_FONT_FLAGS)
2064 			fState->font.SetFlags(font->Flags());
2065 	}
2066 
2067 	fState->font_flags = mask;
2068 
2069 	if (fOwner) {
2070 		check_lock();
2071 		do_owner_check();
2072 
2073 		fState->UpdateServerFontState(*fOwner->fLink);
2074 	}
2075 }
2076 
2077 
2078 #if !_PR3_COMPATIBLE_
2079 void
2080 BView::GetFont(BFont *font) const
2081 #else
2082 void
2083 BView:GetFont(BFont *font)
2084 #endif
2085 {
2086 	*font = fState->font;
2087 }
2088 
2089 
2090 void
2091 BView::GetFontHeight(font_height *height) const
2092 {
2093 	fState->font.GetHeight(height);
2094 }
2095 
2096 
2097 void
2098 BView::SetFontSize(float size)
2099 {
2100 	BFont font;
2101 	font.SetSize(size);
2102 
2103 	SetFont(&font, B_FONT_SIZE);
2104 }
2105 
2106 
2107 float
2108 BView::StringWidth(const char *string) const
2109 {
2110 	return fState->font.StringWidth(string);
2111 }
2112 
2113 
2114 float
2115 BView::StringWidth(const char* string, int32 length) const
2116 {
2117 	return fState->font.StringWidth(string, length);
2118 }
2119 
2120 
2121 void
2122 BView::GetStringWidths(char *stringArray[],int32 lengthArray[],
2123 	int32 numStrings, float widthArray[]) const
2124 {
2125 	fState->font.GetStringWidths(const_cast<const char **>(stringArray),
2126 		const_cast<const int32 *>(lengthArray), numStrings, widthArray);
2127 }
2128 
2129 
2130 void
2131 BView::TruncateString(BString *in_out, uint32 mode, float width) const
2132 {
2133 	fState->font.TruncateString(in_out, mode, width);
2134 }
2135 
2136 
2137 void
2138 BView::ClipToPicture(BPicture *picture, BPoint where, bool sync)
2139 {
2140 	DoPictureClip(picture, where, false, sync);
2141 }
2142 
2143 
2144 void
2145 BView::ClipToInversePicture(BPicture *picture,
2146 	BPoint where, bool sync)
2147 {
2148 	DoPictureClip(picture, where, true, sync);
2149 }
2150 
2151 
2152 void
2153 BView::GetClippingRegion(BRegion* region) const
2154 {
2155 	if (!region)
2156 		return;
2157 
2158 	// TODO: For now, the clipping bit is ignored, since the client has no
2159 	// idea when the clipping in the server changed. -Stephan
2160 
2161 //	if (!fState->IsValid(B_VIEW_CLIP_REGION_BIT) && fOwner && do_owner_check()) {
2162 	if (fOwner && do_owner_check()) {
2163 		fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION);
2164 
2165  		int32 code;
2166  		if (fOwner->fLink->FlushWithReply(code) == B_OK
2167  			&& code == SERVER_TRUE) {
2168 			int32 count;
2169 			fOwner->fLink->Read<int32>(&count);
2170 
2171 			fState->clipping_region.MakeEmpty();
2172 
2173 			for (int32 i = 0; i < count; i++) {
2174 				BRect rect;
2175 				fOwner->fLink->Read<BRect>(&rect);
2176 
2177 				fState->clipping_region.Include(rect);
2178 			}
2179 			fState->valid_flags |= B_VIEW_CLIP_REGION_BIT;
2180 		}
2181 	} else {
2182 		fState->clipping_region.MakeEmpty();
2183 	}
2184 
2185 	*region = fState->clipping_region;
2186 }
2187 
2188 
2189 void
2190 BView::ConstrainClippingRegion(BRegion* region)
2191 {
2192 	if (do_owner_check()) {
2193 		int32 count = 0;
2194 		if (region)
2195 			count = region->CountRects();
2196 
2197 		fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION);
2198 
2199 		// '0' means that in the app_server, there won't be any 'local'
2200 		// clipping region (it will be = NULL)
2201 
2202 		// TODO: note this in the specs
2203 		fOwner->fLink->Attach<int32>(count);
2204 		for (int32 i = 0; i < count; i++)
2205 			fOwner->fLink->Attach<BRect>(region->RectAt(i));
2206 
2207 		// we flush here because app_server waits for all the rects
2208 		fOwner->fLink->Flush();
2209 
2210 		fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT;
2211 		fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT;
2212 	}
2213 }
2214 
2215 
2216 //	#pragma mark - Drawing Functions
2217 //---------------------------------------------------------------------------
2218 
2219 
2220 void
2221 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect)
2222 {
2223 	if (!bitmap || !srcRect.IsValid() || !dstRect.IsValid())
2224 		return;
2225 
2226 	if (fOwner) {
2227 		check_lock();
2228 
2229 		fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT);
2230 		fOwner->fLink->Attach<int32>(bitmap->get_server_token());
2231 		fOwner->fLink->Attach<BRect>(dstRect);
2232 		fOwner->fLink->Attach<BRect>(srcRect);
2233 	}
2234 }
2235 
2236 
2237 void
2238 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect dstRect)
2239 {
2240 	if (!bitmap || !dstRect.IsValid())
2241 		return;
2242 
2243 	DrawBitmapAsync(bitmap, bitmap->Bounds(), dstRect);
2244 }
2245 
2246 
2247 void
2248 BView::DrawBitmapAsync(const BBitmap *bitmap)
2249 {
2250 	DrawBitmapAsync(bitmap, PenLocation());
2251 }
2252 
2253 
2254 void
2255 BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where)
2256 {
2257 	if (bitmap == NULL)
2258 		return;
2259 
2260 	if (fOwner) {
2261 		check_lock();
2262 
2263 		fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT);
2264 		fOwner->fLink->Attach<int32>(bitmap->get_server_token());
2265 		fOwner->fLink->Attach<BPoint>(where);
2266 	}
2267 }
2268 
2269 
2270 void
2271 BView::DrawBitmap(const BBitmap *bitmap)
2272 {
2273 	DrawBitmap(bitmap, PenLocation());
2274 }
2275 
2276 
2277 void
2278 BView::DrawBitmap(const BBitmap *bitmap, BPoint where)
2279 {
2280 	if (bitmap == NULL)
2281 		return;
2282 
2283 	if (fOwner) {
2284 		check_lock();
2285 
2286 		fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT);
2287 		fOwner->fLink->Attach<int32>(bitmap->get_server_token());
2288 		fOwner->fLink->Attach<BPoint>(where);
2289 		fOwner->fLink->Flush();
2290 	}
2291 }
2292 
2293 
2294 void
2295 BView::DrawBitmap(const BBitmap *bitmap, BRect dstRect)
2296 {
2297 	if (!bitmap || !dstRect.IsValid())
2298 		return;
2299 
2300 	DrawBitmap(bitmap, bitmap->Bounds(), dstRect);
2301 }
2302 
2303 
2304 void
2305 BView::DrawBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect)
2306 {
2307 	if ( !bitmap || !srcRect.IsValid() || !dstRect.IsValid())
2308 		return;
2309 
2310 	if (fOwner) {
2311 		check_lock();
2312 
2313 		fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT);
2314 		fOwner->fLink->Attach<int32>(bitmap->get_server_token());
2315 		fOwner->fLink->Attach<BRect>(dstRect);
2316 		fOwner->fLink->Attach<BRect>(srcRect);
2317 		fOwner->fLink->Flush();
2318 	}
2319 }
2320 
2321 
2322 void
2323 BView::DrawChar(char c)
2324 {
2325 	DrawString(&c, 1, PenLocation());
2326 }
2327 
2328 
2329 void
2330 BView::DrawChar(char c, BPoint location)
2331 {
2332 	DrawString(&c, 1, location);
2333 }
2334 
2335 
2336 void
2337 BView::DrawString(const char *string, escapement_delta *delta)
2338 {
2339 	DrawString(string, strlen(string), PenLocation(), delta);
2340 }
2341 
2342 
2343 void
2344 BView::DrawString(const char *string, BPoint location, escapement_delta *delta)
2345 {
2346 	DrawString(string, strlen(string), location, delta);
2347 }
2348 
2349 
2350 void
2351 BView::DrawString(const char *string, int32 length, escapement_delta *delta)
2352 {
2353 	DrawString(string, length, PenLocation(), delta);
2354 }
2355 
2356 
2357 void
2358 BView::DrawString(const char *string, int32 length, BPoint location,
2359 	escapement_delta *delta)
2360 {
2361 	if (string == NULL || length < 1)
2362 		return;
2363 
2364 	if (fOwner) {
2365 		check_lock();
2366 
2367 		fOwner->fLink->StartMessage(AS_DRAW_STRING);
2368 		fOwner->fLink->Attach<int32>(length);
2369 		fOwner->fLink->Attach<BPoint>(location);
2370 
2371 		// Quite often delta will be NULL, so we have to accomodate this.
2372 		if (delta)
2373 			fOwner->fLink->Attach<escapement_delta>(*delta);
2374 		else {
2375 			escapement_delta tdelta;
2376 			tdelta.space = 0;
2377 			tdelta.nonspace = 0;
2378 
2379 			fOwner->fLink->Attach<escapement_delta>(tdelta);
2380 		}
2381 
2382 		fOwner->fLink->AttachString(string, length);
2383 
2384 		// this modifies our pen location, so we invalidate the flag.
2385 		fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
2386 	}
2387 }
2388 
2389 
2390 void
2391 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius,
2392 	pattern p)
2393 {
2394 	StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
2395 		center.y + yRadius), p);
2396 }
2397 
2398 
2399 void
2400 BView::StrokeEllipse(BRect rect, ::pattern pattern)
2401 {
2402 	if (fOwner == NULL)
2403 		return;
2404 
2405 	check_lock();
2406 	_UpdatePattern(pattern);
2407 
2408 	fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE);
2409 	fOwner->fLink->Attach<BRect>(rect);
2410 }
2411 
2412 
2413 void
2414 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
2415 	::pattern pattern)
2416 {
2417 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
2418 		center.x + xRadius, center.y + yRadius), pattern);
2419 }
2420 
2421 
2422 void
2423 BView::FillEllipse(BRect rect, ::pattern pattern)
2424 {
2425 	if (fOwner == NULL)
2426 		return;
2427 
2428 	check_lock();
2429 	_UpdatePattern(pattern);
2430 
2431 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE);
2432 	fOwner->fLink->Attach<BRect>(rect);
2433 }
2434 
2435 
2436 void
2437 BView::StrokeArc(BPoint center, float xRadius, float yRadius,
2438 	float startAngle, float arcAngle, pattern p)
2439 {
2440 	StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
2441 		center.y + yRadius), startAngle, arcAngle, p);
2442 }
2443 
2444 
2445 void
2446 BView::StrokeArc(BRect rect, float startAngle, float arcAngle,
2447 	::pattern pattern)
2448 {
2449 	if (fOwner == NULL)
2450 		return;
2451 
2452 	check_lock();
2453 	_UpdatePattern(pattern);
2454 
2455 	fOwner->fLink->StartMessage(AS_STROKE_ARC);
2456 	fOwner->fLink->Attach<BRect>(rect);
2457 	fOwner->fLink->Attach<float>(startAngle);
2458 	fOwner->fLink->Attach<float>(arcAngle);
2459 }
2460 
2461 
2462 void
2463 BView::FillArc(BPoint center,float xRadius, float yRadius,
2464 	float startAngle, float arcAngle, ::pattern pattern)
2465 {
2466 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
2467 		center.y + yRadius), startAngle, arcAngle, pattern);
2468 }
2469 
2470 
2471 void
2472 BView::FillArc(BRect rect, float startAngle, float arcAngle,
2473 	::pattern pattern)
2474 {
2475 	if (fOwner == NULL)
2476 		return;
2477 
2478 	check_lock();
2479 	_UpdatePattern(pattern);
2480 
2481 	fOwner->fLink->StartMessage(AS_FILL_ARC);
2482 	fOwner->fLink->Attach<BRect>(rect);
2483 	fOwner->fLink->Attach<float>(startAngle);
2484 	fOwner->fLink->Attach<float>(arcAngle);
2485 }
2486 
2487 
2488 void
2489 BView::StrokeBezier(BPoint *controlPoints, ::pattern pattern)
2490 {
2491 	if (fOwner == NULL)
2492 		return;
2493 
2494 	check_lock();
2495 	_UpdatePattern(pattern);
2496 
2497 	fOwner->fLink->StartMessage(AS_STROKE_BEZIER);
2498 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
2499 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
2500 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
2501 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
2502 }
2503 
2504 
2505 void
2506 BView::FillBezier(BPoint *controlPoints, ::pattern pattern)
2507 {
2508 	if (fOwner == NULL)
2509 		return;
2510 
2511 	check_lock();
2512 	_UpdatePattern(pattern);
2513 
2514 	fOwner->fLink->StartMessage(AS_FILL_BEZIER);
2515 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
2516 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
2517 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
2518 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
2519 }
2520 
2521 
2522 void
2523 BView::StrokePolygon(const BPolygon *polygon, bool closed, pattern p)
2524 {
2525 	if (!polygon)
2526 		return;
2527 
2528 	StrokePolygon(polygon->fPts, polygon->fCount, polygon->Frame(), closed, p);
2529 }
2530 
2531 
2532 void
2533 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, bool closed, pattern p)
2534 {
2535 	BPolygon polygon(ptArray, numPoints);
2536 
2537 	StrokePolygon(polygon.fPts, polygon.fCount, polygon.Frame(), closed, p);
2538 }
2539 
2540 
2541 void
2542 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, BRect bounds,
2543 	bool closed, ::pattern pattern)
2544 {
2545 	if (!ptArray
2546 		|| numPoints <= 1
2547 		|| fOwner == NULL)
2548 		return;
2549 
2550 	check_lock();
2551 	_UpdatePattern(pattern);
2552 
2553 	BPolygon polygon(ptArray, numPoints);
2554 	polygon.MapTo(polygon.Frame(), bounds);
2555 
2556 	if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON,
2557 			polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool) + sizeof(int32))
2558 				== B_OK) {
2559 		fOwner->fLink->Attach<BRect>(polygon.Frame());
2560 		fOwner->fLink->Attach<bool>(closed);
2561 		fOwner->fLink->Attach<int32>(polygon.fCount);
2562 		fOwner->fLink->Attach(polygon.fPts, polygon.fCount * sizeof(BPoint));
2563 	} else {
2564 		// TODO: send via an area
2565 		fprintf(stderr, "ERROR: polygon to big for BPortLink!\n");
2566 	}
2567 }
2568 
2569 
2570 void
2571 BView::FillPolygon(const BPolygon *polygon, ::pattern pattern)
2572 {
2573 	if (polygon == NULL
2574 		|| polygon->fCount <= 2
2575 		|| fOwner == NULL)
2576 		return;
2577 
2578 	check_lock();
2579 	_UpdatePattern(pattern);
2580 
2581 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON,
2582 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32)) == B_OK) {
2583 		fOwner->fLink->Attach<BRect>(polygon->Frame());
2584 		fOwner->fLink->Attach<int32>(polygon->fCount);
2585 		fOwner->fLink->Attach(polygon->fPts, polygon->fCount * sizeof(BPoint));
2586 	} else {
2587 		// TODO: send via an area
2588 		fprintf(stderr, "ERROR: polygon to big for BPortLink!\n");
2589 	}
2590 }
2591 
2592 
2593 void
2594 BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern)
2595 {
2596 	if (!ptArray)
2597 		return;
2598 
2599 	BPolygon polygon(ptArray, numPts);
2600 	FillPolygon(&polygon, pattern);
2601 }
2602 
2603 
2604 void
2605 BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds,
2606 	pattern p)
2607 {
2608 	if (!ptArray)
2609 		return;
2610 
2611 	BPolygon polygon(ptArray, numPts);
2612 
2613 	polygon.MapTo(polygon.Frame(), bounds);
2614 	FillPolygon(&polygon, p);
2615 }
2616 
2617 
2618 void
2619 BView::StrokeRect(BRect rect, ::pattern pattern)
2620 {
2621 	if (fOwner == NULL)
2622 		return;
2623 
2624 	check_lock();
2625 	_UpdatePattern(pattern);
2626 
2627 	fOwner->fLink->StartMessage(AS_STROKE_RECT);
2628 	fOwner->fLink->Attach<BRect>(rect);
2629 }
2630 
2631 
2632 void
2633 BView::FillRect(BRect rect, ::pattern pattern)
2634 {
2635 	if (fOwner == NULL)
2636 		return;
2637 
2638 	check_lock();
2639 	_UpdatePattern(pattern);
2640 
2641 	fOwner->fLink->StartMessage(AS_FILL_RECT);
2642 	fOwner->fLink->Attach<BRect>(rect);
2643 }
2644 
2645 
2646 void
2647 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius,
2648 	::pattern pattern)
2649 {
2650 	if (fOwner == NULL)
2651 		return;
2652 
2653 	check_lock();
2654 	_UpdatePattern(pattern);
2655 
2656 	fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT);
2657 	fOwner->fLink->Attach<BRect>(rect);
2658 	fOwner->fLink->Attach<float>(xRadius);
2659 	fOwner->fLink->Attach<float>(yRadius);
2660 }
2661 
2662 
2663 void
2664 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
2665 	::pattern pattern)
2666 {
2667 	if (fOwner == NULL)
2668 		return;
2669 
2670 	check_lock();
2671 
2672 	_UpdatePattern(pattern);
2673 
2674 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT);
2675 	fOwner->fLink->Attach<BRect>(rect);
2676 	fOwner->fLink->Attach<float>(xRadius);
2677 	fOwner->fLink->Attach<float>(yRadius);
2678 }
2679 
2680 
2681 void
2682 BView::FillRegion(BRegion *region, ::pattern pattern)
2683 {
2684 	if (region == NULL || fOwner == NULL)
2685 		return;
2686 
2687 	check_lock();
2688 
2689 	_UpdatePattern(pattern);
2690 
2691 	int32 count = region->CountRects();
2692 
2693 	if (count * sizeof(BRect) < MAX_ATTACHMENT_SIZE) {
2694 		fOwner->fLink->StartMessage(AS_FILL_REGION);
2695 		fOwner->fLink->Attach<int32>(count);
2696 
2697 		for (int32 i = 0; i < count; i++)
2698 			fOwner->fLink->Attach<BRect>(region->RectAt(i));
2699 	} else {
2700 		// TODO: send via area
2701 	}
2702 }
2703 
2704 
2705 void
2706 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3,
2707 	BRect bounds, ::pattern pattern)
2708 {
2709 	if (fOwner == NULL)
2710 		return;
2711 
2712 	check_lock();
2713 
2714 	_UpdatePattern(pattern);
2715 
2716 	fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE);
2717 	fOwner->fLink->Attach<BPoint>(pt1);
2718 	fOwner->fLink->Attach<BPoint>(pt2);
2719 	fOwner->fLink->Attach<BPoint>(pt3);
2720 	fOwner->fLink->Attach<BRect>(bounds);
2721 }
2722 
2723 
2724 void
2725 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p)
2726 {
2727 	if (fOwner) {
2728 		// we construct the smallest rectangle that contains the 3 points
2729 		// for the 1st point
2730 		BRect bounds(pt1, pt1);
2731 
2732 		// for the 2nd point
2733 		if (pt2.x < bounds.left)
2734 			bounds.left = pt2.x;
2735 
2736 		if (pt2.y < bounds.top)
2737 			bounds.top = pt2.y;
2738 
2739 		if (pt2.x > bounds.right)
2740 			bounds.right = pt2.x;
2741 
2742 		if (pt2.y > bounds.bottom)
2743 			bounds.bottom = pt2.y;
2744 
2745 		// for the 3rd point
2746 		if (pt3.x < bounds.left)
2747 			bounds.left = pt3.x;
2748 
2749 		if (pt3.y < bounds.top)
2750 			bounds.top = pt3.y;
2751 
2752 		if (pt3.x > bounds.right)
2753 			bounds.right = pt3.x;
2754 
2755 		if (pt3.y > bounds.bottom)
2756 			bounds.bottom = pt3.y;
2757 
2758 		StrokeTriangle(pt1, pt2, pt3, bounds, p);
2759 	}
2760 }
2761 
2762 
2763 void
2764 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p)
2765 {
2766 	if (fOwner) {
2767 		// we construct the smallest rectangle that contains the 3 points
2768 		// for the 1st point
2769 		BRect bounds(pt1, pt1);
2770 
2771 		// for the 2nd point
2772 		if (pt2.x < bounds.left)
2773 			bounds.left = pt2.x;
2774 
2775 		if (pt2.y < bounds.top)
2776 			bounds.top = pt2.y;
2777 
2778 		if (pt2.x > bounds.right)
2779 			bounds.right = pt2.x;
2780 
2781 		if (pt2.y > bounds.bottom)
2782 			bounds.bottom = pt2.y;
2783 
2784 		// for the 3rd point
2785 		if (pt3.x < bounds.left)
2786 			bounds.left = pt3.x;
2787 
2788 		if (pt3.y < bounds.top)
2789 			bounds.top = pt3.y;
2790 
2791 		if (pt3.x > bounds.right)
2792 			bounds.right = pt3.x;
2793 
2794 		if (pt3.y > bounds.bottom)
2795 			bounds.bottom = pt3.y;
2796 
2797 		FillTriangle(pt1, pt2, pt3, bounds, p);
2798 	}
2799 }
2800 
2801 
2802 void
2803 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3,
2804 	BRect bounds, ::pattern pattern)
2805 {
2806 	if (fOwner == NULL)
2807 		return;
2808 
2809 	check_lock();
2810 	_UpdatePattern(pattern);
2811 
2812 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE);
2813 	fOwner->fLink->Attach<BPoint>(pt1);
2814 	fOwner->fLink->Attach<BPoint>(pt2);
2815 	fOwner->fLink->Attach<BPoint>(pt3);
2816 	fOwner->fLink->Attach<BRect>(bounds);
2817 }
2818 
2819 
2820 void
2821 BView::StrokeLine(BPoint toPt, pattern p)
2822 {
2823 	StrokeLine(PenLocation(), toPt, p);
2824 }
2825 
2826 
2827 void
2828 BView::StrokeLine(BPoint pt0, BPoint pt1, ::pattern pattern)
2829 {
2830 	if (fOwner == NULL)
2831 		return;
2832 
2833 	check_lock();
2834 	_UpdatePattern(pattern);
2835 
2836 	fOwner->fLink->StartMessage(AS_STROKE_LINE);
2837 	fOwner->fLink->Attach<BPoint>(pt0);
2838 	fOwner->fLink->Attach<BPoint>(pt1);
2839 
2840 	// this modifies our pen location, so we invalidate the flag.
2841 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
2842 }
2843 
2844 
2845 void
2846 BView::StrokeShape(BShape *shape, ::pattern pattern)
2847 {
2848 	if (shape == NULL || fOwner == NULL)
2849 		return;
2850 
2851 	shape_data *sd = (shape_data *)shape->fPrivateData;
2852 	if (sd->opCount == 0 || sd->ptCount == 0)
2853 		return;
2854 
2855 	check_lock();
2856 	_UpdatePattern(pattern);
2857 
2858 	if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) {
2859 		fOwner->fLink->StartMessage(AS_STROKE_SHAPE);
2860 		fOwner->fLink->Attach<BRect>(shape->Bounds());
2861 		fOwner->fLink->Attach<int32>(sd->opCount);
2862 		fOwner->fLink->Attach<int32>(sd->ptCount);
2863 		fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32));
2864 		fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
2865 	} else {
2866 		// TODO: send via an area
2867 	}
2868 }
2869 
2870 
2871 void
2872 BView::FillShape(BShape *shape, ::pattern pattern)
2873 {
2874 	if (shape == NULL || fOwner == NULL)
2875 		return;
2876 
2877 	shape_data *sd = (shape_data *)(shape->fPrivateData);
2878 	if (sd->opCount == 0 || sd->ptCount == 0)
2879 		return;
2880 
2881 	check_lock();
2882 	_UpdatePattern(pattern);
2883 
2884 	if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) {
2885 		fOwner->fLink->StartMessage(AS_FILL_SHAPE);
2886 		fOwner->fLink->Attach<BRect>(shape->Bounds());
2887 		fOwner->fLink->Attach<int32>(sd->opCount);
2888 		fOwner->fLink->Attach<int32>(sd->ptCount);
2889 		fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32));
2890 		fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint));
2891 	} else {
2892 		// TODO: send via an area
2893 		// BTW, in a perfect world, the fLink API would take care of that -- axeld.
2894 	}
2895 }
2896 
2897 
2898 void
2899 BView::BeginLineArray(int32 count)
2900 {
2901 	if (fOwner == NULL)
2902 		return;
2903 
2904 	if (count <= 0)
2905 		debugger("Calling BeginLineArray with a count <= 0");
2906 
2907 	check_lock_no_pick();
2908 
2909 	if (comm) {
2910 		delete [] comm->array;
2911 		delete comm;
2912 	}
2913 
2914 	comm = new _array_data_;
2915 
2916 	comm->maxCount = count;
2917 	comm->count = 0;
2918 	comm->array = new _array_hdr_[count];
2919 }
2920 
2921 
2922 void
2923 BView::AddLine(BPoint pt0, BPoint pt1, rgb_color col)
2924 {
2925 	if (fOwner == NULL)
2926 		return;
2927 
2928 	if (!comm)
2929 		debugger("BeginLineArray must be called before using AddLine");
2930 
2931 	check_lock_no_pick();
2932 
2933 	if (comm->count < comm->maxCount) {
2934 		comm->array[comm->count].startX = pt0.x;
2935 		comm->array[comm->count].startY = pt0.y;
2936 		comm->array[comm->count].endX = pt1.x;
2937 		comm->array[comm->count].endY = pt1.y;
2938 
2939 		set_rgb_color(comm->array[comm->count].color,
2940 			col.red, col.green, col.blue, col.alpha);
2941 
2942 		comm->count++;
2943 	}
2944 }
2945 
2946 
2947 void
2948 BView::EndLineArray()
2949 {
2950 	if (fOwner == NULL)
2951 		return;
2952 
2953 	if (!comm)
2954 		debugger("Can't call EndLineArray before BeginLineArray");
2955 
2956 	check_lock();
2957 
2958 	fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY);
2959 	fOwner->fLink->Attach<int32>(comm->count);
2960 	fOwner->fLink->Attach(comm->array, comm->count * sizeof(_array_hdr_));
2961 
2962 	delete [] comm->array;
2963 	delete comm;
2964 	comm = NULL;
2965 }
2966 
2967 
2968 void
2969 BView::BeginPicture(BPicture *picture)
2970 {
2971 	if (do_owner_check() && picture && picture->usurped == NULL) {
2972 		picture->usurp(cpicture);
2973 		cpicture = picture;
2974 
2975 		fOwner->fLink->StartMessage(AS_LAYER_BEGIN_PICTURE);
2976 	}
2977 }
2978 
2979 
2980 void
2981 BView::AppendToPicture(BPicture *picture)
2982 {
2983 	check_lock();
2984 
2985 	if (picture && picture->usurped == NULL) {
2986 		int32 token = picture->token;
2987 
2988 		if (token == -1) {
2989 			BeginPicture(picture);
2990 		} else {
2991 			picture->usurped = cpicture;
2992 			picture->set_token(-1);
2993 			fOwner->fLink->StartMessage(AS_LAYER_APPEND_TO_PICTURE);
2994 			fOwner->fLink->Attach<int32>(token);
2995 		}
2996 	}
2997 }
2998 
2999 
3000 BPicture *
3001 BView::EndPicture()
3002 {
3003 	if (do_owner_check() && cpicture) {
3004 		int32 token;
3005 
3006 		fOwner->fLink->StartMessage(AS_LAYER_END_PICTURE);
3007 
3008 		int32 code;
3009 		if (fOwner->fLink->FlushWithReply(code) == B_OK
3010 			&& code == SERVER_TRUE
3011 			&& fOwner->fLink->Read<int32>(&token) == B_OK) {
3012 			BPicture *picture = cpicture;
3013 			cpicture = picture->step_down();
3014 			picture->set_token(token);
3015 
3016 			return picture;
3017 		}
3018 	}
3019 
3020 	return NULL;
3021 }
3022 
3023 
3024 void
3025 BView::SetViewBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect,
3026 	uint32 followFlags, uint32 options)
3027 {
3028 	setViewImage(bitmap, srcRect, dstRect, followFlags, options);
3029 }
3030 
3031 
3032 void
3033 BView::SetViewBitmap(const BBitmap *bitmap, uint32 followFlags, uint32 options)
3034 {
3035 	BRect rect;
3036  	if (bitmap)
3037 		rect = bitmap->Bounds();
3038 
3039  	rect.OffsetTo(0, 0);
3040 
3041 	setViewImage(bitmap, rect, rect, followFlags, options);
3042 }
3043 
3044 
3045 void
3046 BView::ClearViewBitmap()
3047 {
3048 	setViewImage(NULL, BRect(), BRect(), 0, 0);
3049 }
3050 
3051 
3052 status_t
3053 BView::SetViewOverlay(const BBitmap *overlay, BRect srcRect, BRect dstRect,
3054 	rgb_color *colorKey, uint32 followFlags, uint32 options)
3055 {
3056 	status_t err = setViewImage(overlay, srcRect, dstRect, followFlags,
3057 		options | 0x4);
3058 
3059 	// TODO: Incomplete?
3060 
3061 	// read the color that will be treated as transparent
3062 	fOwner->fLink->Read<rgb_color>(colorKey);
3063 
3064 	return err;
3065 }
3066 
3067 
3068 status_t
3069 BView::SetViewOverlay(const BBitmap *overlay, rgb_color *colorKey,
3070 	uint32 followFlags, uint32 options)
3071 {
3072 	BRect rect;
3073  	if (overlay)
3074 		rect = overlay->Bounds();
3075 
3076  	rect.OffsetTo(0, 0);
3077 
3078 	status_t err = setViewImage(overlay, rect, rect, followFlags,
3079 			options | 0x4);
3080 
3081 	// TODO: Incomplete?
3082 
3083 	// read the color that will be treated as transparent
3084 	fOwner->fLink->Read<rgb_color>(colorKey);
3085 
3086 	return err;
3087 }
3088 
3089 
3090 void
3091 BView::ClearViewOverlay()
3092 {
3093 	setViewImage(NULL, BRect(), BRect(), 0, 0);
3094 }
3095 
3096 
3097 void
3098 BView::CopyBits(BRect src, BRect dst)
3099 {
3100 	if (!src.IsValid() || !dst.IsValid())
3101 		return;
3102 
3103 	if (do_owner_check()) {
3104 		fOwner->fLink->StartMessage(AS_LAYER_COPY_BITS);
3105 		fOwner->fLink->Attach<BRect>(src);
3106 		fOwner->fLink->Attach<BRect>(dst);
3107 	}
3108 }
3109 
3110 
3111 void
3112 BView::DrawPicture(const BPicture *picture)
3113 {
3114 	if (picture == NULL)
3115 		return;
3116 
3117 	DrawPictureAsync(picture, PenLocation());
3118 	fOwner->fLink->Attach<int32>(SERVER_TRUE);
3119 
3120 	// ToDo: why a reply?
3121 	int32 code;
3122 	if (fOwner->fLink->FlushWithReply(code) == B_OK
3123 		&& code == SERVER_TRUE) {
3124 		status_t err;
3125 		fOwner->fLink->Read<int32>(&err);
3126 	}
3127 }
3128 
3129 
3130 void
3131 BView::DrawPicture(const BPicture *picture, BPoint where)
3132 {
3133 	if (picture == NULL)
3134 		return;
3135 
3136 	DrawPictureAsync(picture, where);
3137 	fOwner->fLink->Attach<int32>(SERVER_TRUE);
3138 
3139 	// ToDo: why a reply?
3140 	int32 code;
3141 	if (fOwner->fLink->FlushWithReply(code) == B_OK
3142 		&& code == SERVER_TRUE) {
3143 		status_t err;
3144 		fOwner->fLink->Read<int32>(&err);
3145 	}
3146 }
3147 
3148 
3149 void
3150 BView::DrawPicture(const char *filename, long offset, BPoint where)
3151 {
3152 	if (!filename)
3153 		return;
3154 
3155 	DrawPictureAsync(filename, offset, where);
3156 	fOwner->fLink->Attach<int32>(SERVER_TRUE);
3157 
3158 	// ToDo: why a reply?
3159 	int32 code;
3160 	if (fOwner->fLink->FlushWithReply(code) == B_OK
3161 		&& code == SERVER_TRUE) {
3162 		status_t err;
3163 		fOwner->fLink->Read<int32>(&err);
3164 	}
3165 }
3166 
3167 
3168 void
3169 BView::DrawPictureAsync(const BPicture *picture)
3170 {
3171 	if (picture == NULL)
3172 		return;
3173 
3174 	DrawPictureAsync(picture, PenLocation());
3175 }
3176 
3177 
3178 void
3179 BView::DrawPictureAsync(const BPicture *picture, BPoint where)
3180 {
3181 	if (picture == NULL)
3182 		return;
3183 
3184 	if (do_owner_check() && picture->token > 0) {
3185 		fOwner->fLink->StartMessage(AS_LAYER_DRAW_PICTURE);
3186 		fOwner->fLink->Attach<int32>(picture->token);
3187 		fOwner->fLink->Attach<BPoint>(where);
3188 	}
3189 }
3190 
3191 
3192 void
3193 BView::DrawPictureAsync(const char *filename, long offset, BPoint where)
3194 {
3195 	if (!filename)
3196 		return;
3197 
3198 	// TODO: test and implement
3199 }
3200 
3201 
3202 void
3203 BView::Invalidate(BRect invalRect)
3204 {
3205 	if (!invalRect.IsValid() || fOwner == NULL)
3206 		return;
3207 
3208 	check_lock();
3209 
3210 	fOwner->fLink->StartMessage(AS_LAYER_INVAL_RECT);
3211 	fOwner->fLink->Attach<BRect>(invalRect);
3212 	fOwner->fLink->Flush();
3213 }
3214 
3215 
3216 void
3217 BView::Invalidate(const BRegion *invalRegion)
3218 {
3219 	if (invalRegion == NULL || fOwner == NULL)
3220 		return;
3221 
3222 	check_lock();
3223 
3224 	int32 count = 0;
3225 	count = const_cast<BRegion*>(invalRegion)->CountRects();
3226 
3227 	fOwner->fLink->StartMessage(AS_LAYER_INVAL_REGION);
3228 	fOwner->fLink->Attach<int32>(count);
3229 
3230 	for (int32 i = 0; i < count; i++)
3231 		fOwner->fLink->Attach<BRect>( const_cast<BRegion *>(invalRegion)->RectAt(i));
3232 
3233 	fOwner->fLink->Flush();
3234 }
3235 
3236 
3237 void
3238 BView::Invalidate()
3239 {
3240 	Invalidate(Bounds());
3241 }
3242 
3243 
3244 void
3245 BView::InvertRect(BRect rect)
3246 {
3247 	if (fOwner) {
3248 		check_lock();
3249 
3250 		fOwner->fLink->StartMessage(AS_LAYER_INVERT_RECT);
3251 		fOwner->fLink->Attach<BRect>(rect);
3252 	}
3253 }
3254 
3255 
3256 //	#pragma mark -
3257 //	View Hierarchy Functions
3258 
3259 
3260 void
3261 BView::AddChild(BView *child, BView *before)
3262 {
3263 	STRACE(("BView(%s)::AddChild(child='%s' before='%s')\n",
3264  		this->Name() ? this->Name(): "NULL",
3265  		child && child->Name() ? child->Name(): "NULL",
3266  		before && before->Name() ? before->Name(): "NULL"));
3267 
3268 	if (!child)
3269 		return;
3270 
3271 	if (child->fParent != NULL)
3272 		debugger("AddChild failed - the view already has a parent.");
3273 
3274 	bool lockedByAddChild = false;
3275 	if (fOwner && !fOwner->IsLocked()) {
3276 		fOwner->Lock();
3277 		lockedByAddChild = true;
3278 	}
3279 
3280 	if (!_AddChildToList(child, before))
3281 		debugger("AddChild failed - cannot find 'before' view.");
3282 
3283 	if (fOwner) {
3284 		check_lock();
3285 
3286  		STRACE(("BView(%s)::AddChild(child='%s' before='%s')... contacting app_server\n",
3287  			Name(), child ? child->Name() : "NULL", before ? before->Name() : "NULL"));
3288 
3289 		child->_SetOwner(fOwner);
3290 		attachView(child);
3291 		callAttachHooks(child);
3292 
3293 		if (lockedByAddChild)
3294 			fOwner->Unlock();
3295 	}
3296 
3297 //	BVTRACE;
3298 //	PrintTree();
3299 //	PrintToStream();
3300 }
3301 
3302 
3303 bool
3304 BView::RemoveChild(BView *child)
3305 {
3306 	STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name()));
3307 
3308 	if (!child)
3309 		return false;
3310 
3311 	return child->RemoveSelf();
3312 }
3313 
3314 
3315 int32
3316 BView::CountChildren() const
3317 {
3318 	check_lock_no_pick();
3319 
3320 	uint32 count = 0;
3321 	BView *child = fFirstChild;
3322 
3323 	while (child != NULL) {
3324 		count++;
3325 		child = child->fNextSibling;
3326 	}
3327 
3328 	return count;
3329 }
3330 
3331 
3332 BView *
3333 BView::ChildAt(int32 index) const
3334 {
3335 	check_lock_no_pick();
3336 
3337 	BView *child = fFirstChild;
3338 	while (child != NULL && index-- > 0) {
3339 		child = child->fNextSibling;
3340 	}
3341 
3342 	return child;
3343 }
3344 
3345 
3346 BView *
3347 BView::NextSibling() const
3348 {
3349 	return fNextSibling;
3350 }
3351 
3352 
3353 BView *
3354 BView::PreviousSibling() const
3355 {
3356 	return fPreviousSibling;
3357 }
3358 
3359 
3360 bool
3361 BView::RemoveSelf()
3362 {
3363 	STRACE(("BView(%s)::RemoveSelf()...\n", Name()));
3364 
3365 	// Remove this child from its parent
3366 
3367 	if (fOwner) {
3368 		_UpdateStateForRemove();
3369 	}
3370 
3371 	if (!fParent || !fParent->_RemoveChildFromList(this))
3372 		return false;
3373 
3374 	if (fOwner) {
3375 		check_lock();
3376 
3377 		if (!fState->IsAllValid()) {
3378 			// we need to retrieve the latest state from the server
3379 			fState->UpdateFrom(*fOwner->fLink);
3380 		}
3381 
3382 		// make sure our owner doesn't need us anymore
3383 
3384 		if (fOwner->fDefaultButton == this)
3385 			fOwner->SetDefaultButton(NULL);
3386 
3387 		if (fOwner->fKeyMenuBar == this)
3388 			fOwner->fKeyMenuBar = NULL;
3389 
3390 		if (fOwner->fLastMouseMovedView == this)
3391 			fOwner->fLastMouseMovedView = NULL;
3392 
3393 		if (fOwner->fLastViewToken == _get_object_token_(this))
3394 			fOwner->fLastViewToken = B_NULL_TOKEN;
3395 
3396 		callDetachHooks(this);
3397 
3398 		BWindow *owner = fOwner;
3399 		_SetOwner(NULL);
3400 
3401 		owner->fLink->StartMessage(AS_LAYER_DELETE);
3402 	}
3403 
3404 	STRACE(("DONE: BView(%s)::removeSelf()\n", Name()));
3405 
3406 	return true;
3407 }
3408 
3409 
3410 BView *
3411 BView::Parent() const
3412 {
3413 	if (fParent && fParent->top_level_view)
3414 		return NULL;
3415 
3416 	return fParent;
3417 }
3418 
3419 
3420 BView *
3421 BView::FindView(const char *name) const
3422 {
3423 	if (name == NULL)
3424 		return NULL;
3425 
3426 	if (Name() != NULL && !strcmp(Name(), name))
3427 		return const_cast<BView *>(this);
3428 
3429 	BView *child = fFirstChild;
3430 	while (child != NULL) {
3431 		BView *view = child->FindView(name);
3432 		if (view != NULL)
3433 			return view;
3434 
3435 		child = child->fNextSibling;
3436 	}
3437 
3438 	return NULL;
3439 }
3440 
3441 
3442 void
3443 BView::MoveBy(float deltaX, float deltaY)
3444 {
3445 	MoveTo(fParentOffset.x + deltaX, fParentOffset.y + deltaY);
3446 }
3447 
3448 
3449 void
3450 BView::MoveTo(BPoint where)
3451 {
3452 	MoveTo(where.x, where.y);
3453 }
3454 
3455 
3456 void
3457 BView::MoveTo(float x, float y)
3458 {
3459 	if (x == fParentOffset.x && y == fParentOffset.y)
3460 		return;
3461 
3462 	// BeBook says we should do this. And it makes sense.
3463 	x = roundf(x);
3464 	y = roundf(y);
3465 
3466 	if (fOwner) {
3467 		check_lock();
3468 		fOwner->fLink->StartMessage(AS_LAYER_MOVE_TO);
3469 		fOwner->fLink->Attach<float>(x);
3470 		fOwner->fLink->Attach<float>(y);
3471 
3472 		fState->valid_flags |= B_VIEW_FRAME_BIT;
3473 	}
3474 
3475 	fParentOffset.Set(x, y);
3476 }
3477 
3478 
3479 void
3480 BView::ResizeBy(float deltaWidth, float deltaHeight)
3481 {
3482 	ResizeTo(fBounds.right + deltaWidth, fBounds.bottom + deltaHeight);
3483 }
3484 
3485 
3486 void
3487 BView::ResizeTo(float width, float height)
3488 {
3489 	// NOTE: I think this check makes sense, but I didn't
3490 	// test what R5 does.
3491 	if (width < 0.0)
3492 		width = 0.0;
3493 	if (height < 0.0)
3494 		height = 0.0;
3495 
3496 	if (width == fBounds.Width() && height == fBounds.Height())
3497 		return;
3498 
3499 	// BeBook says we should do this. And it makes sense.
3500 	width = floorf(width + 0.5);
3501 	height = floorf(height + 0.5);
3502 
3503 	if (fOwner) {
3504 		check_lock();
3505 		fOwner->fLink->StartMessage(AS_LAYER_RESIZE_TO);
3506 		fOwner->fLink->Attach<float>(width);
3507 		fOwner->fLink->Attach<float>(height);
3508 
3509 		fState->valid_flags |= B_VIEW_FRAME_BIT;
3510 	}
3511 
3512 	fBounds.right = fBounds.left + width;
3513 	fBounds.bottom = fBounds.top + height;
3514 }
3515 
3516 
3517 //	#pragma mark -
3518 //	Inherited Methods (from BHandler)
3519 
3520 
3521 status_t
3522 BView::GetSupportedSuites(BMessage *data)
3523 {
3524 	if (data == NULL)
3525 		return B_BAD_VALUE;
3526 
3527 	status_t status = data->AddString("Suites", "suite/vnd.Be-view");
3528 	if (status == B_OK) {
3529 		BPropertyInfo propertyInfo(sViewPropInfo);
3530 
3531 		status = data->AddFlat("message", &propertyInfo);
3532 		if (status == B_OK)
3533 			status = BHandler::GetSupportedSuites(data);
3534 	}
3535 	return status;
3536 }
3537 
3538 
3539 BHandler *
3540 BView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier,
3541 	int32 what,	const char *property)
3542 {
3543 	if (msg->what == B_WINDOW_MOVE_BY
3544 		|| msg->what == B_WINDOW_MOVE_TO)
3545 		return this;
3546 
3547 	BPropertyInfo propertyInfo(sViewPropInfo);
3548 
3549 	switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) {
3550 		case B_ERROR:
3551 			break;
3552 
3553 		case 0:
3554 		case 1:
3555 		case 2:
3556 		case 3:
3557 		case 5:
3558 			return this;
3559 
3560 		case 4:
3561 			if (fShelf) {
3562 				msg->PopSpecifier();
3563 				return fShelf;
3564 			} else {
3565 				BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
3566 
3567 				replyMsg.AddInt32("error", B_NAME_NOT_FOUND);
3568 				replyMsg.AddString("message", "This window doesn't have a self");
3569 				msg->SendReply(&replyMsg);
3570 				return NULL;
3571 			}
3572 			break;
3573 
3574 		case 6:
3575 		case 7:
3576 		case 8:
3577 		{
3578 			if (fFirstChild) {
3579 				BView *child;
3580 				switch (msg->what) {
3581 					case B_INDEX_SPECIFIER:
3582 					{
3583 						int32 index;
3584 						msg->FindInt32("data", &index);
3585 						child = ChildAt(index);
3586 						break;
3587 					}
3588 					case B_REVERSE_INDEX_SPECIFIER:
3589 					{
3590 						int32 rindex;
3591 						msg->FindInt32("data", &rindex);
3592 						child = ChildAt(CountChildren() - rindex);
3593 						break;
3594 					}
3595 					case B_NAME_SPECIFIER:
3596 					{
3597 						const char *name;
3598 						msg->FindString("data", &name);
3599 						child = FindView(name);
3600 						break;
3601 					}
3602 
3603 					default:
3604 						child = NULL;
3605 						break;
3606 				}
3607 
3608 				if (child != NULL) {
3609 					msg->PopSpecifier();
3610 					return child;
3611 				} else {
3612 					BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
3613 					replyMsg.AddInt32("error", B_BAD_INDEX);
3614 					replyMsg.AddString("message", "Cannot find view at/with specified index/name.");
3615 					msg->SendReply(&replyMsg);
3616 					return NULL;
3617 				}
3618 			} else {
3619 				BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
3620 				replyMsg.AddInt32("error", B_NAME_NOT_FOUND);
3621 				replyMsg.AddString("message", "This window doesn't have children.");
3622 				msg->SendReply(&replyMsg);
3623 				return NULL;
3624 			}
3625 			break;
3626 		}
3627 
3628 		default:
3629 			break;
3630 	}
3631 
3632 	return BHandler::ResolveSpecifier(msg, index, specifier, what, property);
3633 }
3634 
3635 
3636 void
3637 BView::MessageReceived(BMessage *msg)
3638 {
3639 	BMessage specifier;
3640 	int32 what;
3641 	const char *prop;
3642 	int32 index;
3643 	status_t err;
3644 
3645 	if (!msg->HasSpecifiers()) {
3646 		BHandler::MessageReceived(msg);
3647 		return;
3648 	}
3649 
3650 	err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop);
3651 	if (err == B_OK) {
3652 		BMessage replyMsg;
3653 
3654 		switch (msg->what) {
3655 			case B_GET_PROPERTY:
3656 			{
3657 				replyMsg.what = B_NO_ERROR;
3658 				replyMsg.AddInt32("error", B_OK);
3659 
3660 				if (strcmp(prop, "Frame") == 0)
3661 					replyMsg.AddRect("result", Frame());
3662 				else if (strcmp(prop, "Hidden") == 0)
3663 					replyMsg.AddBool( "result", IsHidden());
3664 				break;
3665 			}
3666 
3667 			case B_SET_PROPERTY:
3668 			{
3669 				if (strcmp(prop, "Frame") == 0) {
3670 					BRect newFrame;
3671 					if (msg->FindRect("data", &newFrame) == B_OK) {
3672 						MoveTo(newFrame.LeftTop());
3673 						ResizeTo(newFrame.right, newFrame.bottom);
3674 
3675 						replyMsg.what = B_NO_ERROR;
3676 						replyMsg.AddInt32("error", B_OK);
3677 					} else {
3678 						replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
3679 						replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
3680 						replyMsg.AddString("message", "Didn't understand the specifier(s)");
3681 					}
3682 				} else if (strcmp(prop, "Hidden") == 0) {
3683 					bool newHiddenState;
3684 					if (msg->FindBool("data", &newHiddenState) == B_OK) {
3685 						if (!IsHidden() && newHiddenState == true) {
3686 							Hide();
3687 
3688 							replyMsg.what = B_NO_ERROR;
3689 							replyMsg.AddInt32( "error", B_OK);
3690 						}
3691 						else if (IsHidden() && newHiddenState == false) {
3692 							Show();
3693 
3694 							replyMsg.what = B_NO_ERROR;
3695 							replyMsg.AddInt32("error", B_OK);
3696 						} else {
3697 							replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
3698 							replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
3699 							replyMsg.AddString("message", "Didn't understand the specifier(s)");
3700 						}
3701 					} else {
3702 						replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
3703 						replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
3704 						replyMsg.AddString("message", "Didn't understand the specifier(s)");
3705 					}
3706 				}
3707 				break;
3708 			}
3709 
3710 			case B_COUNT_PROPERTIES:
3711 				if (strcmp(prop, "View") == 0) {
3712 					replyMsg.what = B_NO_ERROR;
3713 					replyMsg.AddInt32("error", B_OK);
3714 					replyMsg.AddInt32("result", CountChildren());
3715 				}
3716 				break;
3717 		}
3718 
3719 		msg->SendReply(&replyMsg);
3720 	} else {
3721 		BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
3722 		replyMsg.AddInt32("error" , B_BAD_SCRIPT_SYNTAX);
3723 		replyMsg.AddString("message", "Didn't understand the specifier(s)");
3724 
3725 		msg->SendReply(&replyMsg);
3726 	}
3727 }
3728 
3729 
3730 status_t
3731 BView::Perform(perform_code d, void* arg)
3732 {
3733 	return B_BAD_VALUE;
3734 }
3735 
3736 
3737 //	#pragma mark -
3738 //	Private Functions
3739 
3740 
3741 void
3742 BView::InitData(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
3743 {
3744 	// Info: The name of the view is set by BHandler constructor
3745 
3746 	STRACE(("BView::InitData: enter\n"));
3747 
3748 	// initialize members
3749 	fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
3750 
3751 	// handle rounding
3752 	frame.left = roundf(frame.left);
3753 	frame.top = roundf(frame.top);
3754 	frame.right = roundf(frame.right);
3755 	frame.bottom = roundf(frame.bottom);
3756 
3757 	fParentOffset.Set(frame.left, frame.top);
3758 
3759 	fOwner = NULL;
3760 	fParent = NULL;
3761 	fNextSibling = NULL;
3762 	fPreviousSibling = NULL;
3763 	fFirstChild = NULL;
3764 
3765 	fShowLevel = 0;
3766 	top_level_view = false;
3767 
3768 	cpicture = NULL;
3769 	comm = NULL;
3770 
3771 	fVerScroller = NULL;
3772 	fHorScroller = NULL;
3773 
3774 	f_is_printing = false;
3775 
3776 	fPermanentState = NULL;
3777 	fState = new BPrivate::ViewState;
3778 
3779 	fBounds = frame.OffsetToCopy(B_ORIGIN);
3780 	fShelf = NULL;
3781 	pr_state = NULL;
3782 
3783 	fEventMask = 0;
3784 	fEventOptions = 0;
3785 }
3786 
3787 
3788 void
3789 BView::removeCommArray()
3790 {
3791 	if (comm) {
3792 		delete [] comm->array;
3793 		delete comm;
3794 		comm = NULL;
3795 	}
3796 }
3797 
3798 
3799 void
3800 BView::_SetOwner(BWindow *newOwner)
3801 {
3802 	if (!newOwner)
3803 		removeCommArray();
3804 
3805 	if (fOwner != newOwner && fOwner) {
3806 		if (fOwner->fFocus == this)
3807 			MakeFocus(false);
3808 
3809 		if (fOwner->fLastMouseMovedView == this)
3810 			fOwner->fLastMouseMovedView = NULL;
3811 
3812 		fOwner->RemoveHandler(this);
3813 		if (fShelf)
3814 			fOwner->RemoveHandler(fShelf);
3815 	}
3816 
3817 	if (newOwner && newOwner != fOwner) {
3818 		newOwner->AddHandler(this);
3819 		if (fShelf)
3820 			newOwner->AddHandler(fShelf);
3821 
3822 		if (top_level_view)
3823 			SetNextHandler(newOwner);
3824 		else
3825 			SetNextHandler(fParent);
3826 	}
3827 
3828 	fOwner = newOwner;
3829 
3830 	for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling)
3831 		child->_SetOwner(newOwner);
3832 }
3833 
3834 
3835 void
3836 BView::DoPictureClip(BPicture *picture, BPoint where,
3837 	bool invert, bool sync)
3838 {
3839 	if (!picture)
3840 		return;
3841 
3842 	if (do_owner_check()) {
3843 		fOwner->fLink->StartMessage(AS_LAYER_CLIP_TO_PICTURE);
3844 		fOwner->fLink->Attach<int32>(picture->token);
3845 		fOwner->fLink->Attach<BPoint>(where);
3846 		fOwner->fLink->Attach<bool>(invert);
3847 
3848 		// TODO: I think that "sync" means another thing here:
3849 		// the bebook, at least, says so.
3850 		if (sync)
3851 			fOwner->fLink->Flush();
3852 
3853 		fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT;
3854 	}
3855 
3856 	fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT;
3857 }
3858 
3859 
3860 void
3861 BView::callDetachHooks(BView *view)
3862 {
3863 	view->DetachedFromWindow();
3864 
3865 	BView *child = view->fFirstChild;
3866 	while (child != NULL) {
3867 		view->callDetachHooks(child);
3868 		child = child->fNextSibling;
3869 	}
3870 
3871 	view->AllDetached();
3872 }
3873 
3874 
3875 bool
3876 BView::_RemoveChildFromList(BView* child)
3877 {
3878 	if (child->fParent != this)
3879 		return false;
3880 
3881 	if (fFirstChild == child) {
3882 		// it's the first view in the list
3883 		fFirstChild = child->fNextSibling;
3884 	} else {
3885 		// there must be a previous sibling
3886 		child->fPreviousSibling->fNextSibling = child->fNextSibling;
3887 	}
3888 
3889 	if (child->fNextSibling)
3890 		child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
3891 
3892 	child->fParent = NULL;
3893 	child->fNextSibling = NULL;
3894 	child->fPreviousSibling = NULL;
3895 
3896 	return true;
3897 }
3898 
3899 
3900 bool
3901 BView::_AddChildToList(BView* view, BView* before)
3902 {
3903 	if (!view)
3904 		return false;
3905 
3906 	BView *current = fFirstChild;
3907 	BView *last = current;
3908 
3909 	while (current && current != before) {
3910 		last = current;
3911 		current = current->fNextSibling;
3912 	}
3913 
3914 	if (!current && before)
3915 		return false;
3916 
3917 	// we're at begining of the list, OR between two elements
3918 	if (current) {
3919 		if (current == fFirstChild) {
3920 			view->fNextSibling = current;
3921 			current->fPreviousSibling = view;
3922 			fFirstChild = view;
3923 		} else {
3924 			view->fNextSibling = current;
3925 			view->fPreviousSibling = current->fPreviousSibling;
3926 			current->fPreviousSibling->fNextSibling = view;
3927 			current->fPreviousSibling = view;
3928 		}
3929 	} else {
3930 		// we have reached the end of the list
3931 
3932 		// if last!=NULL then we add to the end. Otherwise, view is the
3933 		// first chiild in the list
3934 		if (last) {
3935 			last->fNextSibling = view;
3936 			view->fPreviousSibling = last;
3937 		} else
3938 			fFirstChild = view;
3939 	}
3940 
3941 	view->fParent = this;
3942 	return true;
3943 }
3944 
3945 void
3946 BView::callAttachHooks(BView *view)
3947 {
3948 	view->AttachedToWindow();
3949 
3950 	BView *child = view->fFirstChild;
3951 	while (child != NULL) {
3952 		view->callAttachHooks(child);
3953 		child = child->fNextSibling;
3954 	}
3955 
3956 	view->AllAttached();
3957 }
3958 
3959 
3960 bool
3961 BView::attachView(BView *view)
3962 {
3963 	// AS_LAYER_CREATE & AS_LAYER_CREATE_ROOT do not use the
3964 	// current view mechanism via check_lock() - the token
3965 	// of the view and its parent are both send to the server.
3966 
3967 	if (view->top_level_view)
3968 		fOwner->fLink->StartMessage(AS_LAYER_CREATE_ROOT);
3969 	else
3970  		fOwner->fLink->StartMessage(AS_LAYER_CREATE);
3971 
3972 	fOwner->fLink->Attach<int32>(_get_object_token_(view));
3973 	fOwner->fLink->AttachString(view->Name());
3974 		// send view's frame. the next line replaces: fOwner->fLink->Attach<BRect>(view->Frame());
3975 	fOwner->fLink->Attach<BRect>(view->fBounds.OffsetToCopy(view->fParentOffset));
3976 	fOwner->fLink->Attach<uint32>(view->ResizingMode());
3977 	fOwner->fLink->Attach<uint32>(view->fEventMask);
3978 	fOwner->fLink->Attach<uint32>(view->fEventOptions);
3979 	fOwner->fLink->Attach<uint32>(view->Flags());
3980 	fOwner->fLink->Attach<bool>(view->IsHidden(view));
3981 	fOwner->fLink->Attach<rgb_color>(view->fState->view_color);
3982 	fOwner->fLink->Attach<int32>(_get_object_token_(this));
3983 	fOwner->fLink->Flush();
3984 
3985 	view->do_owner_check();
3986 	view->fState->UpdateServerState(*fOwner->fLink);
3987 
3988 	// we attach all its children
3989 
3990 	BView *child = view->fFirstChild;
3991 	while (child != NULL) {
3992 		view->attachView(child);
3993 		child = child->fNextSibling;
3994 	}
3995 
3996 	fOwner->fLink->Flush();
3997 
3998 	return true;
3999 }
4000 
4001 
4002 void
4003 BView::deleteView(BView* view)
4004 {
4005 	BView *child = view->fFirstChild;
4006 	while (child != NULL) {
4007 		BView *nextChild = child->fNextSibling;
4008 		deleteView(child);
4009 		child = nextChild;
4010 	}
4011 
4012 	delete view;
4013 }
4014 
4015 
4016 void
4017 BView::_Activate(bool active)
4018 {
4019 	WindowActivated(active);
4020 
4021 	for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling)
4022 		child->_Activate(active);
4023 }
4024 
4025 
4026 void
4027 BView::_Pulse()
4028 {
4029 	if (Flags() & B_PULSE_NEEDED)
4030 		Pulse();
4031 
4032 	for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling)
4033 		child->_Pulse();
4034 }
4035 
4036 
4037 void
4038 BView::_UpdateStateForRemove()
4039 {
4040 	if (!do_owner_check())
4041 		return;
4042 
4043 	fState->UpdateFrom(*fOwner->fLink);
4044 	fBounds = Bounds();
4045 	fParentOffset = LeftTop();
4046 
4047 	// update children as well
4048 
4049 	BView *child = fFirstChild;
4050 	while (child != NULL) {
4051 		child->_UpdateStateForRemove();
4052 		child = child->fNextSibling;
4053 	}
4054 }
4055 
4056 
4057 inline void
4058 BView::_UpdatePattern(::pattern pattern)
4059 {
4060 	if (!fState->IsValid(B_VIEW_PATTERN_BIT) || pattern != fState->pattern)
4061 		SetPattern(pattern);
4062 }
4063 
4064 
4065 BShelf *
4066 BView::shelf() const
4067 {
4068 	return fShelf;
4069 }
4070 
4071 
4072 void
4073 BView::set_shelf(BShelf *shelf)
4074 {
4075 	// TODO: is this all that needs done?
4076 	fShelf = shelf;
4077 }
4078 
4079 
4080 status_t
4081 BView::setViewImage(const BBitmap *bitmap, BRect srcRect,
4082 	BRect dstRect, uint32 followFlags, uint32 options)
4083 {
4084 	if (!do_owner_check())
4085 		return B_ERROR;
4086 
4087 	int32 serverToken = bitmap ? bitmap->get_server_token() : -1;
4088 
4089 	fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_IMAGE);
4090 	fOwner->fLink->Attach<int32>(serverToken);
4091 	fOwner->fLink->Attach<BRect>(srcRect);
4092 	fOwner->fLink->Attach<BRect>(dstRect);
4093 	fOwner->fLink->Attach<int32>(followFlags);
4094 	fOwner->fLink->Attach<int32>(options);
4095 
4096 	// TODO: this needs fixed between here and the server.
4097 	// The server should return whatever error code is needed, whether it
4098 	// is B_OK or whatever, not SERVER_TRUE.
4099 
4100 	status_t status = B_ERROR;
4101 	int32 code;
4102 	if (fOwner->fLink->FlushWithReply(code) == B_OK
4103 		&& code == SERVER_TRUE)
4104 		fOwner->fLink->Read<status_t>(&status);
4105 
4106 	return status;
4107 }
4108 
4109 
4110 void
4111 BView::SetPattern(::pattern pattern)
4112 {
4113 	if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern)
4114 		return;
4115 
4116 	if (fOwner) {
4117 		check_lock();
4118 
4119 		fOwner->fLink->StartMessage(AS_LAYER_SET_PATTERN);
4120 		fOwner->fLink->Attach< ::pattern>(pattern);
4121 
4122 		fState->valid_flags |= B_VIEW_PATTERN_BIT;
4123 	}
4124 
4125 	fState->pattern = pattern;
4126 }
4127 
4128 
4129 bool
4130 BView::do_owner_check() const
4131 {
4132 	STRACE(("BView(%s)::do_owner_check()...", Name()));
4133 
4134 	int32 serverToken = _get_object_token_(this);
4135 
4136 	if (fOwner == NULL) {
4137 		debugger("View method requires owner and doesn't have one.");
4138 		return false;
4139 	}
4140 
4141 	fOwner->check_lock();
4142 
4143 	if (fOwner->fLastViewToken != serverToken) {
4144 		STRACE(("contacting app_server... sending token: %ld\n", serverToken));
4145 		fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER);
4146 		fOwner->fLink->Attach<int32>(serverToken);
4147 
4148 		fOwner->fLastViewToken = serverToken;
4149 	} else
4150 		STRACE(("this is the lastViewToken\n"));
4151 
4152 	return true;
4153 }
4154 
4155 
4156 void
4157 BView::check_lock() const
4158 {
4159 	STRACE(("BView(%s)::check_lock()...", Name() ? Name(): "NULL"));
4160 
4161 	if (!fOwner)
4162 		return;
4163 
4164 	fOwner->check_lock();
4165 
4166 	int32 serverToken = _get_object_token_(this);
4167 
4168 	if (fOwner->fLastViewToken != serverToken) {
4169 		STRACE(("contacting app_server... sending token: %ld\n", serverToken));
4170 		fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER);
4171 		fOwner->fLink->Attach<int32>(serverToken);
4172 
4173 		fOwner->fLastViewToken = serverToken;
4174 	} else {
4175 		STRACE(("quiet2\n"));
4176 	}
4177 }
4178 
4179 
4180 void
4181 BView::check_lock_no_pick() const
4182 {
4183 	if (fOwner)
4184 		fOwner->check_lock();
4185 }
4186 
4187 
4188 bool
4189 BView::do_owner_check_no_pick() const
4190 {
4191 	if (fOwner) {
4192 		fOwner->check_lock();
4193 		return true;
4194 	} else {
4195 		debugger("View method requires owner and doesn't have one.");
4196 		return false;
4197 	}
4198 }
4199 
4200 
4201 void BView::_ReservedView2(){}
4202 void BView::_ReservedView3(){}
4203 void BView::_ReservedView4(){}
4204 void BView::_ReservedView5(){}
4205 void BView::_ReservedView6(){}
4206 void BView::_ReservedView7(){}
4207 void BView::_ReservedView8(){}
4208 
4209 #if !_PR3_COMPATIBLE_
4210 void BView::_ReservedView9(){}
4211 void BView::_ReservedView10(){}
4212 void BView::_ReservedView11(){}
4213 void BView::_ReservedView12(){}
4214 void BView::_ReservedView13(){}
4215 void BView::_ReservedView14(){}
4216 void BView::_ReservedView15(){}
4217 void BView::_ReservedView16(){}
4218 #endif
4219 
4220 
4221 BView::BView(const BView &other)
4222 	: BHandler()
4223 {
4224 	// this is private and not functional, but exported
4225 }
4226 
4227 
4228 BView &
4229 BView::operator=(const BView &other)
4230 {
4231 	// this is private and not functional, but exported
4232 	return *this;
4233 }
4234 
4235 
4236 void
4237 BView::PrintToStream()
4238 {
4239 	printf("BView::PrintToStream()\n");
4240 	printf("\tName: %s\
4241 \tParent: %s\
4242 \tFirstChild: %s\
4243 \tNextSibling: %s\
4244 \tPrevSibling: %s\
4245 \tOwner(Window): %s\
4246 \tToken: %ld\
4247 \tFlags: %ld\
4248 \tView origin: (%f,%f)\
4249 \tView Bounds rectangle: (%f,%f,%f,%f)\
4250 \tShow level: %d\
4251 \tTopView?: %s\
4252 \tBPicture: %s\
4253 \tVertical Scrollbar %s\
4254 \tHorizontal Scrollbar %s\
4255 \tIs Printing?: %s\
4256 \tShelf?: %s\
4257 \tEventMask: %ld\
4258 \tEventOptions: %ld\n",
4259 	Name(),
4260 	fParent ? fParent->Name() : "NULL",
4261 	fFirstChild ? fFirstChild->Name() : "NULL",
4262 	fNextSibling ? fNextSibling->Name() : "NULL",
4263 	fPreviousSibling ? fPreviousSibling->Name() : "NULL",
4264 	fOwner ? fOwner->Name() : "NULL",
4265 	_get_object_token_(this),
4266 	fFlags,
4267 	fParentOffset.x, fParentOffset.y,
4268 	fBounds.left, fBounds.top, fBounds.right, fBounds.bottom,
4269 	fShowLevel,
4270 	top_level_view? "YES" : "NO",
4271 	cpicture? "YES" : "NULL",
4272 	fVerScroller? "YES" : "NULL",
4273 	fHorScroller? "YES" : "NULL",
4274 	f_is_printing? "YES" : "NO",
4275 	fShelf? "YES" : "NO",
4276 	fEventMask,
4277 	fEventOptions);
4278 
4279 	printf("\tState status:\
4280 \t\tLocalCoordianteSystem: (%f,%f)\
4281 \t\tPenLocation: (%f,%f)\
4282 \t\tPenSize: %f\
4283 \t\tHighColor: [%d,%d,%d,%d]\
4284 \t\tLowColor: [%d,%d,%d,%d]\
4285 \t\tViewColor: [%d,%d,%d,%d]\
4286 \t\tPattern: %llx\
4287 \t\tDrawingMode: %d\
4288 \t\tLineJoinMode: %d\
4289 \t\tLineCapMode: %d\
4290 \t\tMiterLimit: %f\
4291 \t\tAlphaSource: %d\
4292 \t\tAlphaFuntion: %d\
4293 \t\tScale: %f\
4294 \t\t(Print)FontAliasing: %s\
4295 \t\tFont Info:\n",
4296 	fState->origin.x, fState->origin.y,
4297 	fState->pen_location.x, fState->pen_location.y,
4298 	fState->pen_size,
4299 	fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha,
4300 	fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha,
4301 	fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha,
4302 	*((uint64*)&(fState->pattern)),
4303 	fState->drawing_mode,
4304 	fState->line_join,
4305 	fState->line_cap,
4306 	fState->miter_limit,
4307 	fState->alpha_source_mode,
4308 	fState->alpha_function_mode,
4309 	fState->scale,
4310 	fState->font_aliasing? "YES" : "NO");
4311 
4312 	fState->font.PrintToStream();
4313 
4314 	// TODO: also print the line array.
4315 }
4316 
4317 
4318 void
4319 BView::PrintTree()
4320 {
4321 	int32 spaces = 2;
4322 	BView *c = fFirstChild; //c = short for: current
4323 	printf( "'%s'\n", Name() );
4324 	if (c != NULL) {
4325 		while(true) {
4326 			// action block
4327 			{
4328 				for (int i = 0; i < spaces; i++)
4329 					printf(" ");
4330 
4331 				printf( "'%s'\n", c->Name() );
4332 			}
4333 
4334 			// go deep
4335 			if (c->fFirstChild) {
4336 				c = c->fFirstChild;
4337 				spaces += 2;
4338 			} else {
4339 				// go right
4340 				if (c->fNextSibling) {
4341 					c = c->fNextSibling;
4342 				} else {
4343 					// go up
4344 					while (!c->fParent->fNextSibling && c->fParent != this) {
4345 						c = c->fParent;
4346 						spaces -= 2;
4347 					}
4348 
4349 					// that enough! We've reached this view.
4350 					if (c->fParent == this)
4351 						break;
4352 
4353 					c = c->fParent->fNextSibling;
4354 					spaces -= 2;
4355 				}
4356 			}
4357 		}
4358 	}
4359 }
4360 
4361 
4362 /* TODO:
4363  	-implement SetDiskMode(). What's with this method? What does it do? test!
4364  		does it has something to do with DrawPictureAsync( filename* .. )?
4365 	-implement DrawAfterChildren()
4366 */
4367