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