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