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