
/////////////////////////////////////////
// START of File: b0_dspla.cpp
/////////////////////////////////////////

//-------------------------------------------------------------------
// COPYRIGHT NOTICE:  This code is protected by Copyright!
//
// Copyright (c) 1994 through 1997 by DPC Technology Corporation.
// All rights reserved.
//
// See files "cf_copyr.h" and "cf_licen.h" for details of
// copyright and license specifications, and contact information.
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//
//	b0_dspla.cpp -- ZAF implementation of:	bf_Pen
//											bf_Brush
//											bf_DispLogFontDim
//											bf_Display
//
//-------------------------------------------------------------------

#include    <cf_api/b0_dspla.hpp>
#include    <cf_api/cf_const.h>
#include	<cf_api/bf_defs.h>
            // Which defines minimum-limits for double vals, etc.

#include    <math.h>

//#include        <cf_api/c0_debug.hpp>

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Pen::bf_Pen(	bf_Color bf_clrUseThisColor )
{
	color_ = bf_clrUseThisColor;
	pen_style_ = CF_PS_SOLID;
	width_ = 1;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Pen::bf_Pen(		bf_Color		bf_clrUseThisColor,
					bf_PenStyle		bf_pstyUseThisStyle,
					int				iWidth )
{
	color_ = bf_clrUseThisColor;
	pen_style_ = bf_pstyUseThisStyle;
	width_ = iWidth;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Pen::~bf_Pen() 
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Brush::bf_Brush( bf_Color bf_clrUseThisColor )
{
	color_ = bf_clrUseThisColor;
	hatch_ = CF_BHAT_NONE;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Brush::bf_Brush(	bf_Color       bf_clrUseThisColor,
					bf_BrushHatch  bf_bhUseThisHatch)
{
	color_ = bf_clrUseThisColor;
	hatch_ = bf_bhUseThisHatch;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Brush::~bf_Brush()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_DispLogFontDim::bf_DispLogFontDim()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_DispLogFontDim::bf_DispLogFontDim(	int /* iWidth */,
                        				int /* jHeight */,
                        				bf_Display * )
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_DispLogFontDim::~bf_DispLogFontDim()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Display::bf_Display (ZafDisplay* zdisplay, ZafWindowObject* view)
{
	zdisplay_ = zdisplay;
	view_ = view;

	//
	//	Set up default attributes
	//

	dsp_pushPen (new bf_Pen (bf_Color (ZAF_CLR_BLACK)));
	dsp_pushBrush (new bf_Brush (bf_Color (ZAF_CLR_WHITE)));
	curr_width_ = 1;

	//
	//	Save current font, since it might well be reset
	//
	dsp_pushFont (new bf_Font (zdisplay_ -> Font ()));
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Display::~bf_Display()
{
	//
	//	Restore saved font
	//
	bf_Font*  font = (bf_Font*) dsp_popFont ();
	zdisplay_ -> SetFont (font -> getZafFont ());
	delete font;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_devToLog( cf_2DRect &r )
{
	ZafRegionStruct		zrsConvertRegion;

    zrsConvertRegion.coordinateType = ZAF_PIXEL;
	zrsConvertRegion.left = r.left();
	zrsConvertRegion.top = r.top();
	zrsConvertRegion.right = r.right();
	zrsConvertRegion.bottom = r.bottom();

    // Convert the region and reset the ref-param:
    zrsConvertRegion.ConvertCoordinates( ZAF_TWIPS );
	r = cf_2DRect( zrsConvertRegion.left, zrsConvertRegion.top,
					zrsConvertRegion.right, zrsConvertRegion.bottom);

	return( TRUE );
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_getVisible( cf_2DRect &r )
{
 	ZafRegionStruct	 visible = view_->ConvertToDrawRegion( view_ );

	r = cf_2DRect ( visible.left, visible.top, visible.right,
					visible.bottom);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_lock()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_logToDev( cf_2DRect& r  )
{
	ZafRegionStruct	 zrsConvertRegion;

    zrsConvertRegion.coordinateType = ZAF_TWIPS;
	zrsConvertRegion.left = r.left();
	zrsConvertRegion.top = r.top();
	zrsConvertRegion.right = r.right();
	zrsConvertRegion.bottom = r.bottom();

    // Convert the region and reset the ref-param:
    zrsConvertRegion.ConvertCoordinates( ZAF_PIXEL );
	r = cf_2DRect( zrsConvertRegion.left, zrsConvertRegion.top,
					zrsConvertRegion.right, zrsConvertRegion.bottom);

	return( TRUE );
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_unlock()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_pushBrush (bf_Brush* brush)
{
	setBrushAttributes (brush);
	brushes_.push (brush);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_pushBrush (bf_Color color)
{
	bf_Brush*	new_brush = new bf_Brush (color);


	setBrushAttributes (new_brush);
	brushes_.push (new_brush);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_pushPen (bf_Pen* pen)
{
	setPenAttributes (pen);
	pens_.push (pen);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_pushPen (bf_Color color)
{
	bf_Pen*		new_pen = new bf_Pen (color);


	setPenAttributes (new_pen);
	pens_.push (new_pen);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_circle( cf_2DPoint		center_pt,
            	        int             radius )
{
	zdisplay_ -> Ellipse (
			center_pt.x () - radius,
			center_pt.y () - radius,
			center_pt.x () + radius,
			center_pt.y () + radius,
			0, 360, curr_width_, true);
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color
bf_Display::dsp_pixel(  int         iX,
						int         iY)
{
	zdisplay_ -> Pixel (iX, iY);
	return (* new bf_Color);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color
bf_Display::dsp_pixel(  int         iX,
            	        int         iY,
               		    bf_Color	bf_clrUseThisColor )
{
	zdisplay_ -> Pixel (iX, iY);
	return (bf_clrUseThisColor);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color
bf_Display::dsp_pixel(  cf_2DPoint bf_2dpUseThisPoint )
{
	return (dsp_pixel (	bf_2dpUseThisPoint.x (),
						bf_2dpUseThisPoint.y ()));
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color
bf_Display::dsp_pixel(  cf_2DPoint     bf_2dpUseThisPoint,
                    bf_Color       bf_clrUseThisColor )
{
	return (dsp_pixel (
			bf_2dpUseThisPoint.x (),
			bf_2dpUseThisPoint.y (),
			bf_clrUseThisColor));
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Brush*
bf_Display::dsp_popBrush()
{
	bf_Brush*	old_curr = (bf_Brush*) brushes_.pop ();
	bf_Brush*	new_curr = (bf_Brush*) brushes_.top ();


	if (new_curr != NULL)
		setBrushAttributes (new_curr);

	return (old_curr);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Pen*
bf_Display::dsp_popPen()
{
	bf_Pen*	old_curr = (bf_Pen*) pens_.pop ();
	bf_Pen*	new_curr = (bf_Pen*) pens_.top ();


	if (new_curr != NULL)
		setPenAttributes (new_curr);

	return (old_curr);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    
bf_Display::dsp_polyline(   cf_2DPoint*    a_bf_2dpStartFrom,
                        int             iNumPoints )
{
	int		i;


	for (i = 0; i < iNumPoints - 1; i++)
	{
		zdisplay_ -> Line (
			a_bf_2dpStartFrom[i].x (),
			a_bf_2dpStartFrom[i].y (),
			a_bf_2dpStartFrom[i + 1].x (),
			a_bf_2dpStartFrom[i + 1].y (),
			curr_width_
			);
		/*
		char buf[80]; sprintf (buf, "display polyline: %d %d %d %d",
			a_bf_2dpStartFrom[i].x (),
			a_bf_2dpStartFrom[i].y (),
			a_bf_2dpStartFrom[i + 1].x (),
			a_bf_2dpStartFrom[i + 1].y ());
		b0_debug (buf);
		*/
	}

	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    
bf_Display::dsp_polygon(    cf_2DPoint*    a_bf_2dpStartFrom,
                        int             iNumPoints )
{
	ZafCoordinate*	points = new ZafCoordinate[2 * iNumPoints];
	int				i;


	//
	//	Convert array of cf_2DPoints to array of integers (x-y pairs)
	//
	for (i = 0; i < iNumPoints; i++)
	{
		points[2 * i] = a_bf_2dpStartFrom[i].x ();
		points[2 * i + 1] = a_bf_2dpStartFrom[i].y ();
	}

	zdisplay_ -> Polygon (iNumPoints, points, curr_width_, true);
	return true;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    
bf_Display::dsp_bitmap( bf_2DBitmap*   /* p_bf_2dbmpUseThisBitMap */,
            	        cf_2DPoint     /* bf_2dpPlaceAt */,
               		    cf_2DRect      /* bf_2drSizedBy */ )
{
	return true;
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void    
bf_Display::dsp_getDirty( cf_2DRect&  r_bf_2drTargetRect )
{
	dsp_getVisible (r_bf_2drTargetRect);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void    
bf_Display::dsp_setDirty()
{
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void    
bf_Display::dsp_pushFont( bf_Font *cf_font )
{
	ZafLogicalFont			zfont;


	//
	//	An internal font has structure but has not been allocated
	//	to the system -- do so now
	//

	if (cf_font -> isInternal ())
	{
	/*
		zfont = zdisplay_ -> AddFont (
				ZAF_FNT_NULL,
				(char*) cf_font -> getName (), 
				cf_font -> getSize ());
		if (zfont != ZAF_FNT_NULL)
		{
			zdisplay_ -> SetFont (zfont);
			cf_font -> setZafFont (zfont);
		}
	*/
	}

	fonts_.push (cf_font);

	//
	//	Now we can reset the base display font
	//

	if ((zfont = cf_font -> getZafFont ()) != ZAF_FNT_NULL)
	{
		zdisplay_ -> SetFont (zfont);
	}
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Font*   
bf_Display::dsp_popFont()
{
	bf_Font*		current_font;


	if ((current_font = (bf_Font*) fonts_.pop ()) == NULL)
	{
		return (NULL);
	}

	//
	//	Internal (auto-spec'd or created on-the-fly) fonts must
	//	be deallocated here.  Other fonts are presumed to be 
	//	deallocated by the user
	//

	if (current_font -> isInternal ())
	{
	/*
		ZafLogicalFont	zfont = current_font -> getZafFont ();
		if (zfont != ZAF_FNT_NULL && zfont >= 5)
		{
			zdisplay_ -> DestroyFont (zfont);
		}
	*/
	}


	//
	//	Presumably one would need to restore the previous font,
	//	but this doesn't appear to be necessary
	//
/*
	if ((new_top_font = (bf_Font*) fonts_.top ()) != NULL)
	{
		if (new_top_font -> getZafFont () != ZAF_FNT_NULL)
		{
			//zdisplay_ -> SetFont (new_top_font -> getZafFont ());
		}
		else
		{
			zdisplay_ -> SetFont (ZAF_FNT_DEFAULT);
		}
	}
*/

	return (current_font);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color   
bf_Display::dsp_textColor ()
{
	return (bf_Color (zdisplay_ -> Foreground ()));
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color   
bf_Display::dsp_textColor (bf_Color fg_color)
{
	zdisplay_ -> SetForeground (fg_color);
	return (fg_color);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color   
bf_Display::dsp_backColor()
{
	return (bf_Color (zdisplay_ -> Background ()));
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

bf_Color   
bf_Display::dsp_backColor (bf_Color bg_color)
{
	zdisplay_ -> SetBackground (bg_color);
	return (bg_color);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    
bf_Display::dsp_text(   cf_2DPoint bf_2dpPutTextHere,
            	        char*       szStringAddress     )
{
	zdisplay_ -> Text (
		bf_2dpPutTextHere.x (),
		bf_2dpPutTextHere.y (),
		szStringAddress);
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    
bf_Display::dsp_text(   cf_2DPoint     bf_2dpPutTextHere, 
            	        cf_String      cf_strUseThisString    )
{
	dsp_text (bf_2dpPutTextHere, (char*) cf_strUseThisString);
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

cf_2DRect
bf_Display::dsp_getTextRect(  cf_String string )
{
	return( dsp_getTextRect( (char*) string, string.cf_strlen() ) );
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

cf_2DRect
bf_Display::dsp_getTextRect(  char*   string,
          	                  int     length   )
{
	ZafRegionStruct	zrsTextRect;
    zrsTextRect.coordinateType = ZAF_PIXEL;
    zrsTextRect = zdisplay_->TextSize( string, length );
        // Which *should(?)* be more efficient than the alternative
        // (but equally valid zrsTextRect = zdisplay_->TextSize( string, -1 );

    // We need to do a two-stage return...
	cf_2DRect cf_2drReturnVal(  0, 0,
                                zrsTextRect.Width(), zrsTextRect.Height() );
	return( cf_2drReturnVal );
        // ... because some compilers (e.g. HPUX) complain of
        // constructors inside of return-statement param-lists.
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL    bf_Display::
        dsp_ellipse (cf_2DPoint upper_left,
                     cf_2DPoint lower_right )
{
	zdisplay_ -> Ellipse (
		upper_left.x (), upper_left.y (),
		lower_right.x (), lower_right.y (),
		0, 360, curr_width_, true);
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

double
bf_Display::zz_calcAngleDegrees(  int iOriginX,
          	                      int iOriginY,
           	                     int iRadialX,
           	                     int iRadialY )
{
    // We'll typically compute a degree value from the X,Y-coords...
    double  dAngleInDegrees;
            // ...of two 2D-projected 3D-Point objects...

    // ...by comparing the X.Y position of the origin point to...
    double  dOriginX = (double) iOriginX;
    double  dOriginY = (double) iOriginY;

    // ...the X,Y position of the angle point, and use these vals to...
    double  dRadialX = (double) iRadialX;
    double  dRadialY = (double) iRadialY;

    // ...derive a tangent value...
    double  dAngleRise = dOriginY - dRadialY; // Note Y runs positive DOWNWARDs
    double  dAngleRun = dRadialX - dOriginX;  // and X runs positive to RIGHT.
    double  dAngleTangent;
            // ...which we use to derive a radian value...
    double  dAngleInRadians;
            // ...which we convert (and return) as degree value...

    // First -- screen to protect against div-by-zero and F.P.-overflows:
    if ( ( -1.0 < dAngleRun ) && ( dAngleRun < 1.0 ) )
        ( dAngleRise > 0.0 ? dAngleInDegrees = 90.0 : dAngleInDegrees = 270.0 );
    else
    {
        // Otherwise -- compute the VERY BASIC arc-tan angle...
        #ifdef CF_ASSERT_DVALS
        assert( fabs( dAngleRun ) > CF_NUM_ZERO_IF_LT );
        #endif
        if ( fabs( dAngleRun ) < CF_NUM_ZERO_IF_LT )
            dAngleTangent = 0.0;
        else
            dAngleTangent = ( dAngleRise / dAngleRun );

        dAngleInRadians = atan( dAngleTangent );
            // ...which is valid for Quad #1 only!  We'll have to go through
            // some pain here, because atan only returns between pi/2 and -pi/2.

        // So -- are we REALLY in Quad #1 -- or maybe?...
        if ( ( dAngleRun < 0.0 ) && ( dAngleRise > 0.0 ) )      // ...in Q2?
            dAngleInRadians = CF_PI + dAngleInRadians;
        else if ( ( dAngleRun < 0.0 ) && ( dAngleRise < 0.0 ) ) // ...or Q3?
            dAngleInRadians = CF_PI + dAngleInRadians;
        else if ( ( dAngleRun > 0.0 ) && ( dAngleRise < 0.0 ) ) // ...or Q4?
            dAngleInRadians = CF_2_PI + dAngleInRadians;

        // Now -- convert the radian value to a degree value...
        // while screening and dealing with special cases:
        //if ( dAngleInRadians == 0.0 )
        if ((dAngleInRadians > -(CF_NUM_ZERO_IF_LT)) &&
        	(dAngleInRadians < CF_NUM_ZERO_IF_LT))
            // ...screen and deal with zero-tangents:
            { ( dAngleRun < 0.0 ?
                dAngleInDegrees = 180.0 : dAngleInDegrees = 0.0 ); }

        else if ( ( -1.0 <= dAngleRun ) && ( dAngleRun <= 1.0 ) )
           // deal with the lack of granularity on vertical (and all) angles!
            { ( dAngleRise > 0.0 ?
                dAngleInDegrees = 90.0 : dAngleInDegrees = 270.0 ); }

        else// ...and hoping to keep the fairly accurate angle value...
            dAngleInDegrees = dAngleInRadians * CF_180_OVER_PI;
            // ...from incorrectly rounding to an inaccurate int value!
    }

    return( dAngleInDegrees ); // as calculated (hopefully correctly!) above.

}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_pie(    cf_2DRect  bf_2drBoundaryEllipseRect,
            		    cf_2DPoint bf_2dpStartArcPoint,
                		cf_2DPoint bf_2dpEndArcPoint )
{
    int     iLeft = bf_2drBoundaryEllipseRect.left();
    int     iTop = bf_2drBoundaryEllipseRect.top();
    int     iRight = bf_2drBoundaryEllipseRect.right();
    int     iBottom = bf_2drBoundaryEllipseRect.bottom();

    // OK -- we're gonna hafta convert from 2D-Points to ANGLE
    // values.  Let's proceed by calculating a double-angle-value
    // and converting it to a ZAF-compliant int-degree-value:
    int     iCenterX = iRight - ( ( iRight - iLeft ) / 2 );
    int     iCenterY = iBottom - ( ( iBottom - iTop ) / 2 );
    int     iPointX = bf_2dpStartArcPoint.x();
    int     iPointY = bf_2dpStartArcPoint.y();
            // In *this* implementation, it's best to start from the bottom
            // to avoid wierdness with start angles of zero degrees!...

    // Convert the start-angle X-Y-point to an starting angle -- in DEGREES:

    double	startAngle

            = this->zz_calcAngleDegrees(  iCenterX, iCenterY,
                                                bf_2dpStartArcPoint.x(),
                                                bf_2dpStartArcPoint.y() );
    //int     iStartAngleInDegrees = (int) (startAngle + .5);
    double dStartAngleInDegrees = startAngle;
                                                // cast to a (hopefully) usably
                                                // accurate int-degree-value
                                                // to use below!


    // Convert the end-angle X-Y-point to an ending angle -- in DEGREES:
    double	endAngle
            = this->zz_calcAngleDegrees(  iCenterX, iCenterY,
                                                bf_2dpEndArcPoint.x(),
                                                bf_2dpEndArcPoint.y() );
    //int     iEndAngleInDegrees = (int) (endAngle + .5);
    double dEndAngleInDegrees = endAngle;
                                                // cast as per immed. above.

    // Now!  Let's shove our shiny fresh angle values in a ZAF ellipse call!
    if (dEndAngleInDegrees == 0.0)
    	dEndAngleInDegrees = 360;
	zdisplay_->Ellipse( iLeft, iTop, iRight, iBottom,
		                dStartAngleInDegrees, dEndAngleInDegrees,
                        curr_width_, true );  // true ==> FILLED pie-slice
                        // ... and see what comes out!
    

	/*
	char buf[200];
	sprintf (buf, "pie: %3d %3d %3d %3d [%3d %3d %3d %3d] (%3d-%3d) (%f %f)",
			iLeft, iTop, iRight, iBottom,
			iCenterX, iCenterY, iPointX, iPointY,
			iStartAngleInDegrees, iEndAngleInDegrees,
			startAngle, endAngle);
	b0_debug (buf);
	*/
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_arc(    cf_2DRect  bf_2drBoundaryEllipseRect,
                cf_2DPoint bf_2dpStartArcPoint,
                cf_2DPoint bf_2dpEndArcPoint )
{
    // Avoid overhead of pulling basic info out more than once...
    int     iLeft = bf_2drBoundaryEllipseRect.left();
    int     iTop = bf_2drBoundaryEllipseRect.top();
    int     iRight = bf_2drBoundaryEllipseRect.right();
    int     iBottom = bf_2drBoundaryEllipseRect.bottom();
            // ...by paying for this info now w/ some method calls.

    // OK -- we're gonna hafta convert from 2D-Points to ANGLE
    // values.  Let's proceed by calculating a double-angle-value
    // and converting it to a ZAF-compliant int-degree-value:
    int     iCenterX = iRight - ( ( iRight - iLeft ) / 2 );
    int     iCenterY = iBottom - ( ( iBottom - iTop ) / 2 );
            // In *this* implementation, it's best to start from the bottom
            // to avoid wierdness with start angles of zero degrees!...

    // Convert the start-angle X-Y-point to an starting angle -- in DEGREES:
    double     dStartAngleInDegrees
            = this->zz_calcAngleDegrees(  iCenterX, iCenterY,
                                                bf_2dpStartArcPoint.x(),
                                                bf_2dpStartArcPoint.y() );
                                                // cast to a (hopefully) usably
                                                // accurate int-degree-value
                                                // to use below!

    // Convert the end-angle X-Y-point to an ending angle -- in DEGREES:
    double     dEndAngleInDegrees
            = this->zz_calcAngleDegrees(  iCenterX, iCenterY,
                                                bf_2dpEndArcPoint.x(),
                                                bf_2dpEndArcPoint.y() );
                                                // cast as per immed. above.

    // Now!  Let's shove our shiny fresh angle values in a ZAF ellipse call!
    if (dEndAngleInDegrees == 0.0)
    	dEndAngleInDegrees = 360.0;
	zdisplay_->Ellipse( iLeft, iTop, iRight, iBottom,
		                dStartAngleInDegrees, dEndAngleInDegrees,
                        curr_width_, false );  // false ==> EMPTY arc
                        // ... and see what comes out!
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_drawModeSolid()
{
	zdisplay_ -> SetMode (ZAF_MODE_COPY);  // ### transparent?
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::dsp_drawModeTransparent()
{
	zdisplay_ -> SetMode (ZAF_MODE_XOR);  // ### transparent?
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_rectangle (cf_2DRect rect)
{
	zdisplay_ -> Rectangle (
			rect.left (),
			rect.top (),
			rect.right(),
			rect.bottom (),
			curr_width_);
	return (true);
}




    
//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

BOOL
bf_Display::dsp_polyline (cf_2DRect  rect)
{
	zdisplay_ -> Line (
			rect.left (), rect.top (),
			rect.right(), rect.top (),
			curr_width_
			);
	zdisplay_ -> Line (
			rect.right(), rect.top (),
			rect.right(), rect.bottom (),
			curr_width_
			);
	zdisplay_ -> Line (
			rect.right(), rect.bottom (),
			rect.left (), rect.bottom (),
			curr_width_
			);
	zdisplay_ -> Line (
			rect.left (), rect.bottom (),
			rect.left (), rect.top (),
			curr_width_
			);
	return (true);
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::setBrushAttributes (bf_Brush* brush)
{
	zdisplay_ -> SetBackground (brush -> getColor ());
	zdisplay_ -> SetFillPattern (
			(ZafLogicalFillPattern) brush -> getBrushHatch ());
}





//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

void
bf_Display::setPenAttributes( bf_Pen* pen)
{
	zdisplay_ -> SetForeground (pen -> getColor() );
	zdisplay_ -> SetLineStyle ((ZafLogicalLineStyle) 
			pen->getPenStyle() );
	curr_width_ = pen->getWidth();
}




//////////////////////////////////////
// END of File: b0_dspla.CPP
//////////////////////////////////////

