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