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