diff options
| author | nyamatongwe <devnull@localhost> | 2011-09-24 16:18:16 +1000 | 
|---|---|---|
| committer | nyamatongwe <devnull@localhost> | 2011-09-24 16:18:16 +1000 | 
| commit | 74072356f5a85cfffe606901af95f7c175f5aa25 (patch) | |
| tree | a4cf4394f284fff03689378401582bf9f4c1271c /macosx/PlatMacOSX.cxx | |
| parent | b4673067834de0bc4e2ea290d47c2d2aca4cb555 (diff) | |
| download | scintilla-mirror-74072356f5a85cfffe606901af95f7c175f5aa25.tar.gz | |
Removing Carbon platform layer in favour of Cocoa.
Diffstat (limited to 'macosx/PlatMacOSX.cxx')
| -rw-r--r-- | macosx/PlatMacOSX.cxx | 1861 | 
1 files changed, 0 insertions, 1861 deletions
| diff --git a/macosx/PlatMacOSX.cxx b/macosx/PlatMacOSX.cxx deleted file mode 100644 index 381be992d..000000000 --- a/macosx/PlatMacOSX.cxx +++ /dev/null @@ -1,1861 +0,0 @@ -// Scintilla source code edit control -// PlatMacOSX.cxx - implementation of platform facilities on MacOS X/Carbon -// Based on work by Evan Jones (c) 2002 <ejones@uwaterloo.ca> -// Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <cstring> -#include <cstdio> -#include <cstdlib> - -#include <assert.h> - -#include <sys/time.h> - -#include <vector> -#include <map> - -#include <Carbon/Carbon.h> -#include "QuartzTextLayout.h" -#include "TCarbonEvent.h" - -#include "Platform.h" -#include "Scintilla.h" -#include "PlatMacOSX.h" -#include "XPM.h" - -using namespace Scintilla; - -#include "ScintillaWidget.h" - - -extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam); - -inline CGRect PRectangleToCGRect( PRectangle& rc ) { -    return CGRectMake( rc.left, rc.top, rc.Width(), rc.Height() ); -} - -inline PRectangle CGRectToPRectangle( const CGRect& rect ) { -    PRectangle rc; -    rc.left = (int)( rect.origin.x + 0.5 ); -    rc.top = (int)( rect.origin.y + 0.5 ); -    rc.right = (int)( rect.origin.x + rect.size.width + 0.5 ); -    rc.bottom = (int)( rect.origin.y + rect.size.height + 0.5 ); -    return rc; -} - -Scintilla::Point Scintilla::Point::FromLong(long lpoint) { -  return Scintilla::Point( -               Platform::LowShortFromLong(lpoint), -               Platform::HighShortFromLong(lpoint)); -} - -// The Palette is just ignored on Mac OS X. OS X runs "Millions" or "Thousands" of colours. -Scintilla::Palette::Palette() { -} - -Scintilla::Palette::~Palette() { -} - -void Scintilla::Palette::Release() { -} - -// Do nothing if it "wants" a colour. Copy the colour from desired to allocated if it is "finding" a colour. -void Scintilla::Palette::WantFind(ColourPair &cp, bool want) { -    if (want) { -    } else { -        cp.allocated.Set(cp.desired.AsLong()); -    } -} - -void Scintilla::Palette::Allocate(Window &/*w*/) { -    // OS X always runs in thousands or millions of colours -} - -Font::Font() : fid(0) {} - -Font::~Font() { Release(); } - - -void Font::Create(const char *faceName, int /*characterSet*/, -                  int size, bool bold, bool italic, int /*extraFontFlag*/) { -    // TODO: How should I handle the characterSet request? -    Release(); - -    fid = new QuartzTextStyle(); - -    // Find the font -    QuartzFont font( faceName, strlen( faceName ) ); - -    // We set Font, Size, Bold, Italic -    QuartzTextSize textSize( size ); -    QuartzTextBold isBold( bold ); -    QuartzTextItalic isItalic( italic ); - -    // Actually set the attributes -    QuartzTextStyleAttribute* attributes[] = { &font, &textSize, &isBold, &isItalic }; -    reinterpret_cast<QuartzTextStyle*>( fid )->setAttributes( attributes, sizeof( attributes ) / sizeof( *attributes ) ); - -    //ATSStyleRenderingOptions rendering = kATSStyleNoAntiAliasing; -    //reinterpret_cast<QuartzTextStyle*>( fid )->setAttribute( kATSUStyleRenderingOptionsTag, sizeof( rendering ), &rendering ); - -    // TODO: Why do I have to manually set this? -    reinterpret_cast<QuartzTextStyle*>( fid )->setFontFeature( kLigaturesType, kCommonLigaturesOffSelector ); -} - -void Font::Release() { -    if (fid) -            delete reinterpret_cast<QuartzTextStyle*>( fid ); - -    fid = 0; -} - -SurfaceImpl::SurfaceImpl() { -    bitmapData = NULL; // Release will try and delete bitmapData if != NULL -    gc = NULL; -    textLayout = new QuartzTextLayout(NULL); -    Release(); -} - -SurfaceImpl::~SurfaceImpl() { -    Release(); -    delete textLayout; -} - -void SurfaceImpl::Release() { -    textLayout->setContext (NULL); -    if ( bitmapData != NULL ) -        { -        delete[] bitmapData; -        // We only "own" the graphics context if we are a bitmap context -        if ( gc != NULL ) CGContextRelease( gc ); -        } -    bitmapData = NULL; -    gc = NULL; - -    bitmapWidth = 0; -    bitmapHeight = 0; -    x = 0; -    y = 0; -    //inited = false; -} - -bool SurfaceImpl::Initialised() { -    // We are initalised if the graphics context is not null -  return gc != NULL;// || port != NULL; -} - -void SurfaceImpl::Init(WindowID /*wid*/) { -    // To be able to draw, the surface must get a CGContext handle.  We save the graphics port, -    // then aquire/release the context on an as-need basis (see above). -    // XXX Docs on QDBeginCGContext are light, a better way to do this would be good. -    // AFAIK we should not hold onto a context retrieved this way, thus the need for -    // aquire/release of the context. - -    Release(); -} - -void SurfaceImpl::Init(SurfaceID sid, WindowID /*wid*/) { -    Release(); -    gc = reinterpret_cast<CGContextRef>( sid ); -    CGContextSetLineWidth( gc, 1.0 ); -    textLayout->setContext (gc); -} - -void SurfaceImpl::InitPixMap(int width, int height, Surface* /*surface_*/, WindowID /*wid*/) { -    Release(); -    // Create a new bitmap context, along with the RAM for the bitmap itself -    bitmapWidth = width; -    bitmapHeight = height; - -    const int bitmapBytesPerRow   = (width * BYTES_PER_PIXEL); -    const int bitmapByteCount     = (bitmapBytesPerRow * height); - -    // create an RGB color space -    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); -    if( colorSpace == NULL ) -        return; - -    // create the bitmap -    bitmapData = new uint8_t[ bitmapByteCount ]; -    if( bitmapData != NULL ) { -        // create the context -        gc = CGBitmapContextCreate( bitmapData, -                                    width, -                                    height, -                                    BITS_PER_COMPONENT, -                                    bitmapBytesPerRow, -                                    colorSpace, -                                    kCGImageAlphaPremultipliedLast); - -        if( gc == NULL ) { -            // the context couldn't be created for some reason, -            // and we have no use for the bitmap without the context -            delete[] bitmapData; -            bitmapData = NULL; -        } -        textLayout->setContext (gc); -    } - -    // the context retains the color space, so we can release it -    CGColorSpaceRelease( colorSpace ); - -    if ( gc != NULL && bitmapData != NULL ) -    { -        // "Erase" to white -        CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) ); -        CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 ); -        CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) ); -    } -} - -void SurfaceImpl::PenColour(ColourAllocated fore) { -    if (gc) { -        ColourDesired colour( fore.AsLong() ); - -        // Set the Stroke color to match -        CGContextSetRGBStrokeColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, 1.0 ); -    } -} - -void SurfaceImpl::FillColour(const ColourAllocated& back) { -    if (gc) { -        ColourDesired colour( back.AsLong() ); - -        // Set the Fill color to match -        CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, 1.0 ); -    } -} - -CGImageRef SurfaceImpl::GetImage() { -    // For now, assume that GetImage can only be called on PixMap surfaces -    if ( bitmapData == NULL ) return NULL; - -    CGContextFlush( gc ); - -    // create an RGB color space -    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); -    if( colorSpace == NULL ) -        return NULL; - -    const int bitmapBytesPerRow   = ((int) bitmapWidth * BYTES_PER_PIXEL); -    const int bitmapByteCount     = (bitmapBytesPerRow * (int) bitmapHeight); - -    // Create a data provider -    CGDataProviderRef dataProvider = CGDataProviderCreateWithData( NULL, bitmapData, bitmapByteCount, NULL ); -    CGImageRef image = NULL; -    if ( dataProvider != NULL ) -    { -        // create the CGImage -        image = CGImageCreate( bitmapWidth, -                            bitmapHeight, -                            BITS_PER_COMPONENT, -                            BITS_PER_PIXEL, -                            bitmapBytesPerRow, -                            colorSpace, -                            kCGImageAlphaPremultipliedLast, -                            dataProvider, -                            NULL, -                            0, -                            kCGRenderingIntentDefault ); -    } - -    // the image retains the color space, so we can release it -    CGColorSpaceRelease( colorSpace ); -    colorSpace = NULL; - -    // Done with the data provider -    CGDataProviderRelease( dataProvider ); -    dataProvider = NULL; - -    return image; -} - -int SurfaceImpl::LogPixelsY() { -    return 72; -} - -int SurfaceImpl::DeviceHeightFont(int points) { -    int logPix = LogPixelsY(); -    return (points * logPix + logPix / 2) / 72; -} - -void SurfaceImpl::MoveTo(int x_, int y_) { -    x = x_; -    y = y_; -} - -void SurfaceImpl::LineTo(int x_, int y_) { -    CGContextBeginPath( gc ); -    // Because Quartz is based on floating point, lines are drawn with half their colour -    // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel -    // divison lines. If you specify exact pixel values, you get a line that -    // is twice as thick but half as intense. To get pixel aligned rendering, -    // we render the "middle" of the pixels by adding 0.5 to the coordinates. -    CGContextMoveToPoint( gc, x + 0.5, y + 0.5 ); -    CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 ); -    CGContextStrokePath( gc ); -    x = x_; -    y = y_; -} - -void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore, -                      ColourAllocated back) { -    // Allocate memory for the array of points -    CGPoint *points = new CGPoint[ npts ]; - -    for (int i = 0;i < npts;i++) { -        // Quartz floating point issues: plot the MIDDLE of the pixels -        points[i].x = pts[i].x + 0.5; -        points[i].y = pts[i].y + 0.5; -    } - -    CGContextBeginPath( gc ); - -    // Set colours -    FillColour(back); -    PenColour(fore); - -    // Draw the polygon -    CGContextAddLines( gc, points, npts ); -    // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only) -    CGContextClosePath( gc ); -    CGContextDrawPath( gc, kCGPathFillStroke ); - -    // Deallocate memory -    delete [] points; -    points = NULL; -} - -void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { -    if ( gc ) { -        CGContextBeginPath( gc ); -        FillColour(back); -        PenColour(fore); - -        // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo) -        // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined -        // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom. -        CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) ); -        CGContextDrawPath( gc, kCGPathFillStroke ); -    } -} - -void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { -    if ( gc ) { -        //CGContextBeginPath( gc ); -        FillColour(back); - -        CGRect rect = PRectangleToCGRect( rc ); - -        CGContextFillRect( gc, rect ); -        //CGContextDrawPath( gc, kCGPathFill ); -    } -} - -void drawImageRefCallback( CGImageRef pattern, CGContextRef gc ) -{ -    CGContextDrawImage( gc, CGRectMake( 0, 0, CGImageGetWidth( pattern ), CGImageGetHeight( pattern ) ), pattern ); -} - -void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { -    SurfaceImpl& patternSurface = static_cast<SurfaceImpl &>(surfacePattern); - -    // For now, assume that copy can only be called on PixMap surfaces -    // Shows up black -    CGImageRef image = patternSurface.GetImage(); -    if ( image == NULL ) -        { -        FillRectangle(rc, ColourAllocated(0)); -        return; -        } - -    const CGPatternCallbacks drawImageCallbacks = { 0, reinterpret_cast<CGPatternDrawPatternCallback>( drawImageRefCallback ), NULL }; - -    CGPatternRef pattern = CGPatternCreate( image, -                                         CGRectMake( 0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight ), -                                         CGAffineTransformIdentity, -                                         patternSurface.bitmapWidth, -                                         patternSurface.bitmapHeight, -                                         kCGPatternTilingNoDistortion, -                                         true, -                                         &drawImageCallbacks -                                         ); -    if( pattern != NULL ) { - -        // Create a pattern color space -        CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); -        if( colorSpace != NULL ) { - -            CGContextSaveGState( gc ); -            CGContextSetFillColorSpace( gc, colorSpace ); - -            // Unlike the documentation, you MUST pass in a "components" parameter: -            // For coloured patterns it is the alpha value. -            const float alpha = 1.0; -            CGContextSetFillPattern( gc, pattern, &alpha ); -            CGContextFillRect( gc, PRectangleToCGRect( rc ) ); -            CGContextRestoreGState( gc ); -            // Free the color space, the pattern and image -            CGColorSpaceRelease( colorSpace ); -        } /* colorSpace != NULL */ -        colorSpace = NULL; -        CGPatternRelease( pattern ); -        pattern = NULL; -        CGImageRelease( image ); -        image = NULL; -    } /* pattern != NULL */ -} - -void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { -    // This is only called from the margin marker drawing code for SC_MARK_ROUNDRECT -    // The Win32 version does -    //  ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 ); -    // which is a rectangle with rounded corners each having a radius of 4 pixels. -    // It would be almost as good just cutting off the corners with lines at -    // 45 degrees as is done on GTK+. - -    // Create a rectangle with semicircles at the corners -    const int MAX_RADIUS = 4; -    int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 ); -    radius = Platform::Minimum( radius, rc.Width()/2 ); - -    // Points go clockwise, starting from just below the top left -    // Corners are kept together, so we can easily create arcs to connect them -    CGPoint corners[4][3] = -        { -            { -                { rc.left, rc.top + radius }, -                { rc.left, rc.top }, -                { rc.left + radius, rc.top }, -            }, -            { -                { rc.right - radius - 1, rc.top }, -                { rc.right - 1, rc.top }, -                { rc.right - 1, rc.top + radius }, -            }, -            { -                { rc.right - 1, rc.bottom - radius - 1 }, -                { rc.right - 1, rc.bottom - 1 }, -                { rc.right - radius - 1, rc.bottom - 1 }, -            }, -            { -                { rc.left + radius, rc.bottom - 1 }, -                { rc.left, rc.bottom - 1 }, -                { rc.left, rc.bottom - radius - 1 }, -            }, -        }; - -    // Align the points in the middle of the pixels -    for( int i = 0; i < 4*3; ++ i ) -        { -        CGPoint* c = (CGPoint*) corners; -        c[i].x += 0.5; -        c[i].y += 0.5; -        } - -    PenColour( fore ); -    FillColour( back ); - -    // Move to the last point to begin the path -    CGContextBeginPath( gc ); -    CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y ); - -    for ( int i = 0; i < 4; ++ i ) -        { -        CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y ); -        CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius ); -        } - -    // Close the path to enclose it for stroking and for filling, then draw it -    CGContextClosePath( gc ); -    CGContextDrawPath( gc, kCGPathFillStroke ); -} - -void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourAllocated fill, int alphaFill, -                                            ColourAllocated /*outline*/, int /*alphaOutline*/, int /*flags*/) -{ -    if ( gc ) { -        ColourDesired colour( fill.AsLong() ); - -        // Set the Fill color to match -        CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 ); -        CGRect rect = PRectangleToCGRect( rc ); -        CGContextFillRect( gc, rect ); -    } -} - -void SurfaceImpl::DrawRGBAImage(PRectangle /* rc */, int /* width */, int /* height */, const unsigned char * /* pixelsImage*/) { -	// Not supported for Carbon -} - -void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { -    // Drawing an ellipse with bezier curves. Code modified from: -    // http://www.codeguru.com/gdi/ellipse.shtml -    // MAGICAL CONSTANT to map ellipse to beziers 2/3*(sqrt(2)-1) -    const double EToBConst = 0.2761423749154; - -    CGSize offset = CGSizeMake((int)(rc.Width() * EToBConst), (int)(rc.Height() * EToBConst)); -    CGPoint centre = CGPointMake((rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2); - -    // The control point array -    CGPoint cCtlPt[13]; - -    // Assign values to all the control points -    cCtlPt[0].x  = -        cCtlPt[1].x  = -        cCtlPt[11].x = -        cCtlPt[12].x = rc.left + 0.5; -    cCtlPt[5].x  = -        cCtlPt[6].x  = -        cCtlPt[7].x  = rc.right - 0.5; -    cCtlPt[2].x  = -        cCtlPt[10].x = centre.x - offset.width + 0.5; -    cCtlPt[4].x  = -        cCtlPt[8].x  = centre.x + offset.width + 0.5; -    cCtlPt[3].x  = -        cCtlPt[9].x  = centre.x + 0.5; - -    cCtlPt[2].y  = -        cCtlPt[3].y  = -        cCtlPt[4].y  = rc.top + 0.5; -    cCtlPt[8].y  = -        cCtlPt[9].y  = -        cCtlPt[10].y = rc.bottom - 0.5; -    cCtlPt[7].y  = -        cCtlPt[11].y = centre.y + offset.height + 0.5; -    cCtlPt[1].y = -        cCtlPt[5].y  = centre.y - offset.height + 0.5; -    cCtlPt[0].y = -        cCtlPt[12].y = -        cCtlPt[6].y  = centre.y + 0.5; - -    FillColour(back); -    PenColour(fore); - -    CGContextBeginPath( gc ); -    CGContextMoveToPoint( gc, cCtlPt[0].x, cCtlPt[0].y ); - -    for ( int i = 1; i < 13; i += 3 ) -        { -        CGContextAddCurveToPoint( gc, cCtlPt[i].x, cCtlPt[i].y, cCtlPt[i+1].x, cCtlPt[i+1].y, cCtlPt[i+2].x, cCtlPt[i+2].y ); -        } - -    // Close the path to enclose it for stroking and for filling, then draw it -    CGContextClosePath( gc ); -    CGContextDrawPath( gc, kCGPathFillStroke ); -} - -void SurfaceImpl::CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect) -{ -    SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource); -    CGImageRef image = source.GetImage(); - -    CGRect src = PRectangleToCGRect(srcRect); -    CGRect dst = PRectangleToCGRect(dstRect); - -    /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */ -    float w = (float) CGImageGetWidth(image); -    float h = (float) CGImageGetHeight(image); -    CGRect drawRect = CGRectMake (0, 0, w, h); -    if (!CGRectEqualToRect (src, dst)) -    { -        float sx = CGRectGetWidth(dst) / CGRectGetWidth(src); -        float sy = CGRectGetHeight(dst) / CGRectGetHeight(src); -        float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx); -        float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy); -        drawRect = CGRectMake (dx, dy, w*sx, h*sy); -    } -    CGContextSaveGState (gc); -    CGContextClipToRect (gc, dst); -    CGContextDrawImage (gc, drawRect, image); -    CGContextRestoreGState (gc); -} - -void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) { -    // Maybe we have to make the Surface two contexts: -    // a bitmap context which we do all the drawing on, and then a "real" context -    // which we copy the output to when we call "Synchronize". Ugh! Gross and slow! - -    // For now, assume that copy can only be called on PixMap surfaces -    SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource); - -    // Get the CGImageRef -    CGImageRef image = source.GetImage(); -    // If we could not get an image reference, fill the rectangle black -    if ( image == NULL ) -        { -        FillRectangle( rc, ColourAllocated( 0 ) ); -        return; -        } - -    // Now draw the image on the surface - -    // Some fancy clipping work is required here: draw only inside of rc -    CGContextSaveGState( gc ); -    CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); - -    //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ); -    CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image ); - -    // Undo the clipping fun -    CGContextRestoreGState( gc ); - -    // Done with the image -    CGImageRelease( image ); -    image = NULL; -} - -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, -                                 ColourAllocated fore, ColourAllocated back) { - -    FillRectangle(rc, back); -    DrawTextTransparent( rc, font_, ybase, s, len, fore ); -} - -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, -                                  ColourAllocated fore, ColourAllocated back) { - -    CGContextSaveGState( gc ); -    CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); -    DrawTextNoClip( rc, font_, ybase, s, len, fore, back ); -    CGContextRestoreGState( gc ); -} - -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) { -    textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); - -    // The Quartz RGB fill color influences the ATSUI color -    FillColour(fore); -    // Draw the text, with the Y axis flipped -    textLayout->draw( rc.left, ybase, true ); -} - -void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) { -    // sample at http://developer.apple.com/samplecode/ATSUICurveAccessDemo/listing1.html -    // sample includes use of ATSUGetGlyphInfo which would be better for older -    // OSX systems.  We should expand to using that on older systems as well. -    for (int i = 0; i < len; i++) -            positions [i] = 0; - -    // We need the right X coords, so we have to append a char to get the left coord of thast extra char -    char* buf = (char*) malloc (len+1); -    if (!buf) -            return; - -    memcpy (buf, s, len); -    buf [len] = '.'; - -    textLayout->setText (reinterpret_cast<const UInt8*>(buf), len+1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); -    ATSUGlyphInfoArray* theGlyphInfoArrayPtr; -    ByteCount theArraySize; - -    // Get the GlyphInfoArray -    ATSUTextLayout layout = textLayout->getLayout(); -    if ( noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, NULL)) -    { -        theGlyphInfoArrayPtr = (ATSUGlyphInfoArray *) malloc (theArraySize + sizeof(ItemCount) + sizeof(ATSUTextLayout)); -        if (theGlyphInfoArrayPtr) -        { -            if (noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, theGlyphInfoArrayPtr)) -            { -                // do not count the first item, which is at the beginning of the line -                for ( UniCharCount unicodePosition = 1, i = 0; i < len && unicodePosition < theGlyphInfoArrayPtr->numGlyphs; unicodePosition ++ ) -                { -                    // The ideal position is the x coordinate of the glyph, relative to the beginning of the line -                    int position = (int)( theGlyphInfoArrayPtr->glyphs[unicodePosition].idealX + 0.5 );    // These older APIs return float values -                    unsigned char uch = s[i]; -                    positions[i++] = position; - -                    // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters, -                    // as 1 unicode character can map to multiple UTF8 characters. -                    // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF -                    // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html -                    if ( unicodeMode ) -                    { -                        unsigned char mask = 0xc0; -                        int count = 1; -                        // Add one additonal byte for each extra high order one in the byte -                        while ( uch >= mask && count < 8 ) -                        { -                            positions[i++] = position; -                            count ++; -                            mask = mask >> 1 | 0x80; // add an additional one in the highest order position -                        } -                    } -                } -            } - -            // Free the GlyphInfoArray -            free (theGlyphInfoArrayPtr); -        } -    } -    free (buf); -} - -int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { -    if (font_.GetID()) -    { -        textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); - -        // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout? -        unsigned long actualNumberOfBounds = 0; -        ATSTrapezoid glyphBounds; - -        // We get a single bound, since the text should only require one. If it requires more, there is an issue -        if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 ) -        { -            Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthText" ); -            return 0; -        } - -        //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) ); -        return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ); -    } -    return 1; -} - -int SurfaceImpl::WidthChar(Font &font_, char ch) { -    char str[2] = { ch, '\0' }; -    if (font_.GetID()) -    { -        textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); - -        // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout? -        unsigned long actualNumberOfBounds = 0; -        ATSTrapezoid glyphBounds; - -        // We get a single bound, since the text should only require one. If it requires more, there is an issue -        if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 ) -        { -            Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthChar" ); -            return 0; -        } - -        return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ); -    } -    else -        return 1; -} - -// Three possible strategies for determining ascent and descent of font: -// 1) Call ATSUGetGlyphBounds with string containing all letters, numbers and punctuation. -// 2) Use the ascent and descent fields of the font. -// 3) Call ATSUGetGlyphBounds with string as 1 but also including accented capitals. -// Smallest values given by 1 and largest by 3 with 2 in between. -// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and -// descenders but are mostly OK except for accented characters which are -// rarely used in code. - -// This string contains a good range of characters to test for size. -const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" -                          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -int SurfaceImpl::Ascent(Font &font_) { -    if (!font_.GetID()) -        return 1; - -    ATSUTextMeasurement ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUAscentTag ); -    return Fix2Long( ascent ); -} - -int SurfaceImpl::Descent(Font &font_) { -    if (!font_.GetID()) -        return 1; - -    ATSUTextMeasurement descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUDescentTag ); -    return Fix2Long( descent ); -} - -int SurfaceImpl::InternalLeading(Font &) { -    // TODO: How do we get EM_Size? -    // internal leading = ascent - descent - EM_size -    return 0; -} - -int SurfaceImpl::ExternalLeading(Font &font_) { -    if (!font_.GetID()) -        return 1; - -    ATSUTextMeasurement lineGap = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSULeadingTag ); -    return Fix2Long( lineGap ); -} - -int SurfaceImpl::Height(Font &font_) { -    return Ascent(font_) + Descent(font_); -} - -int SurfaceImpl::AverageCharWidth(Font &font_) { - -    if (!font_.GetID()) -        return 1; - -    const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1); -    int width = WidthText( font_, sizeString, sizeStringLength  ); - -    return (int) ((width / (float) sizeStringLength) + 0.5); - -    /* -    ATSUStyle textStyle = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getATSUStyle(); -    ATSUFontID fontID; - -    ByteCount actualSize = 0; -    if ( ATSUGetAttribute( textStyle, kATSUFontTag, sizeof( fontID ), &fontID, &actualSize ) != noErr ) -        { -Platform::DebugDisplay( "ATSUGetAttribute failed" ); -        return 1; -        } - -    ATSFontMetrics metrics; -    memset( &metrics, 0, sizeof( metrics ) ); -    if ( ATSFontGetHorizontalMetrics( fontID, kATSOptionFlagsDefault, &metrics ) != noErr ) -    { -        Platform::DebugDisplay( "ATSFontGetHorizontalMetrics failed in AverageCharWidth" ); -        return 1; -    } - -    printf( "%f %f %f\n", metrics.avgAdvanceWidth * 32, metrics.ascent * 32, metrics.descent * 32 ); - -    return (int) (metrics.avgAdvanceWidth + 0.5);*/ -} - -int SurfaceImpl::SetPalette(Scintilla::Palette *, bool) { -    // Mac OS X is always true colour (I think) so this doesn't matter -    return 0; -} - -void SurfaceImpl::SetClip(PRectangle rc) { -    CGContextClipToRect( gc, PRectangleToCGRect( rc ) ); -} - -void SurfaceImpl::FlushCachedState() { -    CGContextSynchronize( gc ); -} - -void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { -    unicodeMode = unicodeMode_; -} - -void SurfaceImpl::SetDBCSMode(int codePage) { -    // TODO: Implement this for code pages != UTF-8 -} - -Surface *Surface::Allocate() { -    return new SurfaceImpl(  ); -} - -Window::~Window() { -} - -void Window::Destroy() { -    if (windowRef) { -        DisposeWindow(reinterpret_cast<WindowRef>( windowRef )); -    } -    wid = 0; -} - -bool Window::HasFocus() { -    // TODO: Test this -    return HIViewSubtreeContainsFocus( reinterpret_cast<HIViewRef>( wid ) ); -} - -PRectangle Window::GetPosition() { -    // Before any size allocated pretend its 1000 wide so not scrolled -    PRectangle rc(0, 0, 1000, 1000); - -    // The frame rectangle gives the position of this view inside the parent view -    if (wid) { -        HIRect controlFrame; -        HIViewGetFrame( reinterpret_cast<HIViewRef>( wid ), &controlFrame ); -        rc = CGRectToPRectangle( controlFrame ); -    } - -    return rc; -} - -void Window::SetPosition(PRectangle rc) { -    // Moves this view inside the parent view -    if ( wid ) -    { -        // Set the frame on the view, the function handles the rest -        CGRect r = PRectangleToCGRect( rc ); -        HIViewSetFrame( reinterpret_cast<HIViewRef>( wid ), &r ); -    } -} - -void Window::SetPositionRelative(PRectangle rc, Window window) { -    // used to actually move child windows (ie. listbox/calltip) so we have to move -    // the window, not the hiview -    if (windowRef) { -        // we go through some contortions here to get an accurate location for our -        // child windows.  This is necessary due to the multiple ways an embedding -        // app may be setup.  See SciTest/main.c (GOOD && BAD) for test case. -        WindowRef relativeWindow = GetControlOwner(reinterpret_cast<HIViewRef>( window.GetID() )); -        WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef ); - -        Rect portBounds; -        ::GetWindowBounds(relativeWindow, kWindowStructureRgn, &portBounds); -        //fprintf(stderr, "portBounds %d %d %d %d\n", portBounds.left, portBounds.top, portBounds.right, portBounds.bottom); -        PRectangle hbounds = window.GetPosition(); -        //fprintf(stderr, "hbounds %d %d %d %d\n", hbounds.left, hbounds.top, hbounds.right, hbounds.bottom); -        HIViewRef parent = HIViewGetSuperview(reinterpret_cast<HIViewRef>( window.GetID() )); -        Rect pbounds; -        GetControlBounds(parent, &pbounds); -        //fprintf(stderr, "pbounds %d %d %d %d\n", pbounds.left, pbounds.top, pbounds.right, pbounds.bottom); - -        PRectangle bounds; -        bounds.top = portBounds.top + pbounds.top + hbounds.top + rc.top; -        bounds.bottom = bounds.top + rc.Height(); -        bounds.left = portBounds.left + pbounds.left + hbounds.left + rc.left; -        bounds.right = bounds.left + rc.Width(); -        //fprintf(stderr, "bounds %d %d %d %d\n", bounds.left, bounds.top, bounds.right, bounds.bottom); - -        MoveWindow(thisWindow, bounds.left, bounds.top, false); -        SizeWindow(thisWindow, bounds.Width(), bounds.Height(), true); - -        SetPosition(PRectangle(0,0,rc.Width(),rc.Height())); -    } else { -        SetPosition(rc); -    } -} - -PRectangle Window::GetClientPosition() { -    // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32. -    return GetPosition(); -} - -void Window::Show(bool show) { -    if ( wid ) { -        HIViewSetVisible( reinterpret_cast<HIViewRef>( wid ), show ); -    } -    // this is necessary for calltip/listbox -    if (windowRef) { -        WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef ); -        if (show) { -            ShowWindow( thisWindow ); -            DrawControls( thisWindow ); -        } else -            HideWindow( thisWindow ); -    } -} - -void Window::InvalidateAll() { -    if ( wid ) { -        HIViewSetNeedsDisplay( reinterpret_cast<HIViewRef>( wid ), true ); -    } -} - -void Window::InvalidateRectangle(PRectangle rc) { -    if (wid) { -        // Create a rectangular region -        RgnHandle region = NewRgn(); -        SetRectRgn( region, rc.left, rc.top, rc.right, rc.bottom ); - -        // Make that region invalid -        HIViewSetNeedsDisplayInRegion( reinterpret_cast<HIViewRef>( wid ), region, true ); -        DisposeRgn( region ); -    } -} - -void Window::SetFont(Font &) { -    // TODO: Do I need to implement this? MSDN: specifies the font that a control is to use when drawing text. -} - -void Window::SetCursor(Cursor curs) { -    if (wid) { -        // TODO: This isn't really implemented correctly. I should be using -        // mouse tracking rectangles to only set the mouse cursor when it is over the control -        ThemeCursor cursor; - -        switch ( curs ) { -            case cursorText: -                cursor = kThemeIBeamCursor; -                break; -            case cursorArrow: -                cursor = kThemeArrowCursor; -                break; -            case cursorWait: -                cursor = kThemeWatchCursor; -                break; -            case cursorHoriz: -                cursor = kThemeResizeLeftRightCursor; -                break; -            case cursorVert: -                cursor = kThemeResizeUpDownCursor; -                break; -            case cursorReverseArrow: -            case cursorUp: -            default: -                cursor = kThemeArrowCursor; -                break; -        } - -        SetThemeCursor( cursor ); -    } -} - -void Window::SetTitle(const char *s) { -    WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>( wid )); -    CFStringRef title = CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingMacRoman); -    SetWindowTitleWithCFString(window, title); -    CFRelease(title); -} - -PRectangle Window::GetMonitorRect(Point) { -	return PRectangle(); -} - -ListBox::ListBox() {} - -ListBox::~ListBox() {} - -static const OSType scintillaListBoxType = 'sclb'; - -enum { -    kItemsPerContainer = 1, -    kIconColumn = 'icon', -    kTextColumn = 'text' -}; -static SInt32 kScrollBarWidth = 0; - -class LineData { -    int *types; -        CFStringRef *strings; -    int len; -    int maximum; -public: -    LineData() :types(0), strings(0), len(0), maximum(0) {} -    ~LineData() { -        Clear(); -    } -    void Clear() { -        delete []types; -        types = 0; -        for (int i=0; i<maximum; i++) { -          if (strings[i]) CFRelease(strings[i]); -        } -        delete []strings; -        strings = 0; -        len = 0; -        maximum = 0; -    } -    void Add(int index, int type, CFStringRef str ) { -        if (index >= maximum) { -            if (index >= len) { -                int lenNew = (index+1) * 2; -                int *typesNew = new int[lenNew]; -                CFStringRef *stringsNew = new CFStringRef[lenNew]; -                for (int i=0; i<maximum; i++) { -                    typesNew[i] = types[i]; -                    stringsNew[i] = strings[i]; -                } -                delete []types; -                delete []strings; -                types = typesNew; -                strings = stringsNew; -                len = lenNew; -            } -            while (maximum < index) { -                types[maximum] = 0; -                strings[maximum] = 0; -                maximum++; -            } -        } -        types[index] = type; -        strings[index] = str; -        if (index == maximum) { -            maximum++; -        } -    } -    int GetType(int index) { -        if (index < maximum) { -            return types[index]; -        } else { -            return 0; -        } -    } -    CFStringRef GetString(int index) { -        if (index < maximum) { -            return strings[index]; -        } else { -            return 0; -        } -    } -}; - -class ListBoxImpl : public ListBox { -private: -    ControlRef lb; -    XPMSet xset; -    int lineHeight; -    bool unicodeMode; -    int desiredVisibleRows; -    unsigned int maxItemWidth; -    unsigned int aveCharWidth; -    Font font; -    int maxWidth; - -    void InstallDataBrowserCustomCallbacks(); -    void ConfigureDataBrowser(); - -    static pascal OSStatus  WindowEventHandler(EventHandlerCallRef  inCallRef, -                                               EventRef inEvent, -                                               void *inUserData ); -    EventHandlerRef eventHandler; - -protected: -    WindowRef windowRef; - -public: -    LineData ld; -    CallBackAction doubleClickAction; -    void *doubleClickActionData; - -    ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false), -            desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8), -            doubleClickAction(NULL), doubleClickActionData(NULL) -    { -      if (kScrollBarWidth == 0) -        GetThemeMetric(kThemeMetricScrollBarWidth, &kScrollBarWidth); -    } - -    ~ListBoxImpl() {}; -    void SetFont(Font &font); -    void Create(Window &parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_); -    void SetAverageCharWidth(int width); -    void SetVisibleRows(int rows); -    int GetVisibleRows() const; -    PRectangle GetDesiredRect(); -    int CaretFromEdge(); -    void Clear(); -    void Append(char *s, int type = -1); -    int Length(); -    void Select(int n); -    int GetSelection(); -    int Find(const char *prefix); -    void GetValue(int n, char *value, int len); -    void RegisterImage(int type, const char *xpm_data); -    void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); -    void ClearRegisteredImages(); -    void SetDoubleClickAction(CallBackAction action, void *data) { -        doubleClickAction = action; -        doubleClickActionData = data; -    } - -    int IconWidth(); -    void ShowHideScrollbar(); -#ifdef DB_TABLE_ROW_HEIGHT -    void SetRowHeight(DataBrowserItemID itemID); -#endif - -    void DrawRow(DataBrowserItemID item, -                 DataBrowserPropertyID property, -                 DataBrowserItemState itemState, -                 const Rect *theRect); - -    void SetList(const char* list, char separator, char typesep); -}; - -ListBox *ListBox::Allocate() { -    ListBoxImpl *lb = new ListBoxImpl(); -    return lb; -} - -void ListBoxImpl::Create(Window &/*parent*/, int /*ctrlID*/, Scintilla::Point /*pt*/, -                         int lineHeight_, bool unicodeMode_) { -    lineHeight = lineHeight_; -    unicodeMode = unicodeMode_; -    maxWidth = 2000; - -    WindowClass windowClass = kHelpWindowClass; -    WindowAttributes attributes = kWindowNoAttributes; -    Rect contentBounds; -    WindowRef outWindow; - -    contentBounds.top = contentBounds.left = 0; -    contentBounds.right = 100; -    contentBounds.bottom = lineHeight * desiredVisibleRows; - -    CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow); - -    InstallStandardEventHandler(GetWindowEventTarget(outWindow)); - -    ControlRef root; -    CreateRootControl(outWindow, &root); - -    CreateDataBrowserControl(outWindow, &contentBounds, kDataBrowserListView, &lb); - -#ifdef DB_TABLE_ROW_HEIGHT -    // XXX does not seem to have any effect -    SetDataBrowserTableViewRowHeight(lb, lineHeight); -#endif - -    // get rid of the frame, forces databrowser to the full size -    // of the window -    Boolean frameAndFocus = false; -    SetControlData(lb, kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, -           sizeof(frameAndFocus), &frameAndFocus); - -    ListBoxImpl* lbThis = this; -    SetControlProperty( lb, scintillaListBoxType, 0, sizeof( this ), &lbThis ); - -    ConfigureDataBrowser(); -    InstallDataBrowserCustomCallbacks(); - -    // install event handlers -    static const EventTypeSpec kWindowEvents[] = -        { -          { kEventClassMouse, kEventMouseDown }, -          { kEventClassMouse, kEventMouseMoved }, -        }; - -    eventHandler = NULL; -    InstallWindowEventHandler( outWindow, WindowEventHandler, -                   GetEventTypeCount( kWindowEvents ), -                   kWindowEvents, this, &eventHandler ); - -    wid = lb; -    SetControlVisibility(lb, true, true); -    SetControl(lb); -    SetWindow(outWindow); -} - -pascal OSStatus ListBoxImpl::WindowEventHandler( -    EventHandlerCallRef inCallRef, -    EventRef            inEvent, -    void*               inUserData ) -{ - -    switch (GetEventClass(inEvent)) { -    case kEventClassMouse: -      switch (GetEventKind(inEvent)) -        { -        case kEventMouseMoved: -          { -            SetThemeCursor( kThemeArrowCursor ); -            break; -          } -        case kEventMouseDown: -          { -            // we cannot handle the double click from the databrowser notify callback as -            // calling doubleClickAction causes the listbox to be destroyed.  It is -            // safe to do it from this event handler since the destroy event will be queued -            // until we're done here. -            TCarbonEvent        event( inEvent ); -            EventMouseButton inMouseButton; -            event.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton ); - -            UInt32 inClickCount; -            event.GetParameter( kEventParamClickCount, &inClickCount ); -            if (inMouseButton == kEventMouseButtonPrimary && inClickCount == 2) { -              // handle our single mouse click now -              ListBoxImpl* listbox = reinterpret_cast<ListBoxImpl*>( inUserData ); -              const WindowRef window = GetControlOwner(listbox->lb); -              const HIViewRef rootView = HIViewGetRoot( window ); -              HIViewRef targetView = NULL; -              HIViewGetViewForMouseEvent( rootView, inEvent, &targetView ); -              if ( targetView == listbox->lb ) -                { -                  if (listbox->doubleClickAction != NULL) { -                listbox->doubleClickAction(listbox->doubleClickActionData); -                  } -                } -            } -          } -      } -    } -    return eventNotHandledErr; -} - -#ifdef DB_TABLE_ROW_HEIGHT -void ListBoxImpl::SetRowHeight(DataBrowserItemID itemID) -{ -    // XXX does not seem to have any effect -    SetDataBrowserTableViewItemRowHeight(lb, itemID, lineHeight); -} -#endif - -void ListBoxImpl::DrawRow(DataBrowserItemID item, -         DataBrowserPropertyID property, -         DataBrowserItemState itemState, -         const Rect *theRect) -{ -    Rect row = *theRect; -    row.left = 0; - -    ColourPair fore; - -    if (itemState == kDataBrowserItemIsSelected) { -      long        systemVersion; -      Gestalt( gestaltSystemVersion, &systemVersion ); -      //  Panther DB starts using kThemeBrushSecondaryHighlightColor for inactive browser hilighting -      if ( (systemVersion >= 0x00001030) && (IsControlActive( lb ) == false) ) -          SetThemePen( kThemeBrushSecondaryHighlightColor, 32, true ); -      else -        //SetThemePen( kThemeBrushPrimaryHighlightColor, 32, true ); -        SetThemePen( kThemeBrushAlternatePrimaryHighlightColor, 32, true ); - -      PaintRect(&row); -      fore = ColourDesired(0xff,0xff,0xff); -    } - -    int widthPix = xset.GetWidth() + 2; -    int pixId = ld.GetType(item - 1); -    XPM *pxpm = xset.Get(pixId); - -    char s[255]; -    GetValue(item - 1, s, 255); - -    Surface *surfaceItem = Surface::Allocate(); -    if (surfaceItem) { -        CGContextRef    cgContext; -        GrafPtr        port; -        Rect bounds; - -        GetControlBounds(lb, &bounds); -        GetPort( &port ); -        QDBeginCGContext( port, &cgContext ); - -        CGContextSaveGState( cgContext ); -        CGContextTranslateCTM(cgContext, 0, bounds.bottom - bounds.top); -        CGContextScaleCTM(cgContext, 1.0, -1.0); - -        surfaceItem->Init(cgContext, NULL); - -        int left = row.left; -        if (pxpm) { -            PRectangle rc(left + 1, row.top, -                    left + 1 + widthPix, row.bottom); -            pxpm->Draw(surfaceItem, rc); -        } - -        // draw the text -        PRectangle trc(left + 2 + widthPix, row.top, row.right, row.bottom); -        int ascent = surfaceItem->Ascent(font) - surfaceItem->InternalLeading(font); -        int ytext = trc.top + ascent + 1; -        trc.bottom = ytext + surfaceItem->Descent(font) + 1; -        surfaceItem->DrawTextTransparent( trc, font, ytext, s, strlen(s), fore.allocated ); - -        CGContextRestoreGState( cgContext ); -        QDEndCGContext( port, &cgContext ); -        delete surfaceItem; -    } -} - - -pascal void ListBoxDrawItemCallback(ControlRef browser, DataBrowserItemID item, -                    DataBrowserPropertyID property, -                    DataBrowserItemState itemState, -                    const Rect *theRect, SInt16 gdDepth, -                    Boolean colorDevice) -{ -    if (property != kIconColumn) return; -    ListBoxImpl* lbThis = NULL; -    OSStatus err; -    err = GetControlProperty( browser, scintillaListBoxType, 0, sizeof( lbThis ), NULL, &lbThis ); -    // adjust our rect -    lbThis->DrawRow(item, property, itemState, theRect); - -} - -void ListBoxImpl::ConfigureDataBrowser() -{ -    DataBrowserViewStyle viewStyle; -    DataBrowserSelectionFlags selectionFlags; -    ::GetDataBrowserViewStyle(lb, &viewStyle); - -    ::SetDataBrowserHasScrollBars(lb, false, true); -    ::SetDataBrowserListViewHeaderBtnHeight(lb, 0); -    ::GetDataBrowserSelectionFlags(lb, &selectionFlags); -    ::SetDataBrowserSelectionFlags(lb, selectionFlags |= kDataBrowserSelectOnlyOne); -    // if you change the hilite style, also change the style in ListBoxDrawItemCallback -    ::SetDataBrowserTableViewHiliteStyle(lb, kDataBrowserTableViewFillHilite); - -    Rect insetRect; -    ::GetDataBrowserScrollBarInset(lb, &insetRect); - -    insetRect.right = kScrollBarWidth - 1; -    ::SetDataBrowserScrollBarInset(lb, &insetRect); - -    switch (viewStyle) -    { -      case kDataBrowserListView: -      { -        DataBrowserListViewColumnDesc iconCol; -        iconCol.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc; -        iconCol.headerBtnDesc.minimumWidth = 0; -        iconCol.headerBtnDesc.maximumWidth = maxWidth; -        iconCol.headerBtnDesc.titleOffset = 0; -        iconCol.headerBtnDesc.titleString = NULL; -        iconCol.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing; - -        iconCol.headerBtnDesc.btnFontStyle.flags = kControlUseJustMask; -        iconCol.headerBtnDesc.btnFontStyle.just = teFlushLeft; - -        iconCol.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly; - -        iconCol.propertyDesc.propertyID = kIconColumn; -        iconCol.propertyDesc.propertyType = kDataBrowserCustomType; -        iconCol.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn; - -        ::AddDataBrowserListViewColumn(lb, &iconCol, kDataBrowserListViewAppendColumn); -      }  break; - -    } -} - -void ListBoxImpl::InstallDataBrowserCustomCallbacks() -{ -    DataBrowserCustomCallbacks callbacks; - -    callbacks.version = kDataBrowserLatestCustomCallbacks; -    verify_noerr(InitDataBrowserCustomCallbacks(&callbacks)); -    callbacks.u.v1.drawItemCallback = NewDataBrowserDrawItemUPP(ListBoxDrawItemCallback); -    callbacks.u.v1.hitTestCallback = NULL;//NewDataBrowserHitTestUPP(ListBoxHitTestCallback); -    callbacks.u.v1.trackingCallback = NULL;//NewDataBrowserTrackingUPP(ListBoxTrackingCallback); -    callbacks.u.v1.editTextCallback = NULL; -    callbacks.u.v1.dragRegionCallback = NULL; -    callbacks.u.v1.acceptDragCallback = NULL; -    callbacks.u.v1.receiveDragCallback = NULL; - -    SetDataBrowserCustomCallbacks(lb, &callbacks); -} - -void ListBoxImpl::SetFont(Font &font_) { -    // Having to do this conversion is LAME -    QuartzTextStyle *ts = reinterpret_cast<QuartzTextStyle*>( font_.GetID() ); -    ControlFontStyleRec style; -    ATSUAttributeValuePtr value; -    ATSUFontID        fontID; -    style.flags = kControlUseFontMask | kControlUseSizeMask | kControlAddToMetaFontMask; -    ts->getAttribute( kATSUFontTag, sizeof(fontID), &fontID, NULL ); -    ATSUFontIDtoFOND(fontID, &style.font, NULL); -    ts->getAttribute( kATSUSizeTag, sizeof(Fixed), &value, NULL ); -    style.size = ((SInt16)FixRound((SInt32)value)); -    SetControlFontStyle(lb, &style); - -#ifdef DB_TABLE_ROW_HEIGHT -    //  XXX this doesn't *stick* -    ATSUTextMeasurement ascent = ts->getAttribute<ATSUTextMeasurement>( kATSUAscentTag ); -    ATSUTextMeasurement descent = ts->getAttribute<ATSUTextMeasurement>( kATSUDescentTag ); -    lineHeight = Fix2Long( ascent ) + Fix2Long( descent ); -    SetDataBrowserTableViewRowHeight(lb, lineHeight + lineLeading); -#endif - -    // !@&^#%$ we cant copy Font, but we need one for our custom drawing -    Str255 fontName255; -    char fontName[256]; -    FMGetFontFamilyName(style.font, fontName255); - -    CFStringRef fontNameCF = ::CFStringCreateWithPascalString( kCFAllocatorDefault, fontName255, kCFStringEncodingMacRoman ); -    ::CFStringGetCString( fontNameCF, fontName, (CFIndex)255, kCFStringEncodingMacRoman ); - -    font.Create((const char *)fontName, 0, style.size, false, false); -} - -void ListBoxImpl::SetAverageCharWidth(int width) { -        aveCharWidth = width; -} - -void ListBoxImpl::SetVisibleRows(int rows) { -    desiredVisibleRows = rows; -} - -int ListBoxImpl::GetVisibleRows() const { -    // XXX Windows & GTK do this, but it seems incorrect to me.  Other logic -    //     to do with visible rows is essentially the same across platforms. -    return desiredVisibleRows; -    /* -    // This would be more correct -    int rows = Length(); -    if ((rows == 0) || (rows > desiredVisibleRows)) -        rows = desiredVisibleRows; -    return rows; -    */ -} - -PRectangle ListBoxImpl::GetDesiredRect() { -    PRectangle rcDesired = GetPosition(); - -    // XXX because setting the line height on the table doesnt -    //     *stick*, we'll have to suffer and just use whatever -    //     the table desides is the correct height. -    UInt16 itemHeight;// = lineHeight; -    GetDataBrowserTableViewRowHeight(lb, &itemHeight); - -    int rows = Length(); -    if ((rows == 0) || (rows > desiredVisibleRows)) -        rows = desiredVisibleRows; - -    rcDesired.bottom = itemHeight * rows; -    rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth; - -    if (Length() > rows) -        rcDesired.right += kScrollBarWidth; -    rcDesired.right += IconWidth(); - -    // Set the column width -    ::SetDataBrowserTableViewColumnWidth (lb, UInt16 (rcDesired.right - rcDesired.left)); -    return rcDesired; -} - -void ListBoxImpl::ShowHideScrollbar() { -    int rows = Length(); -    if (rows > desiredVisibleRows) { -        ::SetDataBrowserHasScrollBars(lb, false, true); -    } else { -        ::SetDataBrowserHasScrollBars(lb, false, false); -    } -} - -int ListBoxImpl::IconWidth() { -    return xset.GetWidth() + 2; -} - -int ListBoxImpl::CaretFromEdge() { -    return 0; -} - -void ListBoxImpl::Clear() { -    // passing NULL to "items" arg 4 clears the list -    maxItemWidth = 0; -    ld.Clear(); -    AddDataBrowserItems (lb, kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty); -} - -void ListBoxImpl::Append(char *s, int type) { -    int count = Length(); -    CFStringRef r = CFStringCreateWithCString(NULL, s, kTextEncodingMacRoman); -    ld.Add(count, type, r); - -    Scintilla::SurfaceImpl surface; -    unsigned int width = surface.WidthText (font, s, strlen (s)); -    if (width > maxItemWidth) -        maxItemWidth = width; - -    DataBrowserItemID items[1]; -    items[0] = count + 1; -    AddDataBrowserItems (lb, kDataBrowserNoItem, 1, items, kDataBrowserItemNoProperty); -    ShowHideScrollbar(); -} - -void ListBoxImpl::SetList(const char* list, char separator, char typesep) { -    // XXX copied from PlatGTK, should be in base class -    Clear(); -    int count = strlen(list) + 1; -    char *words = new char[count]; -    if (words) { -        memcpy(words, list, count); -        char *startword = words; -        char *numword = NULL; -        int i = 0; -        for (; words[i]; i++) { -            if (words[i] == separator) { -                words[i] = '\0'; -                if (numword) -                    *numword = '\0'; -                Append(startword, numword?atoi(numword + 1):-1); -                startword = words + i + 1; -                numword = NULL; -            } else if (words[i] == typesep) { -                numword = words + i; -            } -        } -        if (startword) { -            if (numword) -                *numword = '\0'; -            Append(startword, numword?atoi(numword + 1):-1); -        } -        delete []words; -    } -} - -int ListBoxImpl::Length() { -    UInt32 numItems = 0; -    GetDataBrowserItemCount(lb, kDataBrowserNoItem, false, kDataBrowserItemAnyState, &numItems); -    return (int)numItems; -} - -void ListBoxImpl::Select(int n) { -    DataBrowserItemID items[1]; -    items[0] = n + 1; -    SetDataBrowserSelectedItems(lb, 1, items, kDataBrowserItemsAssign); -    RevealDataBrowserItem(lb, items[0], kIconColumn, kDataBrowserRevealOnly); -    // force update on selection -    Draw1Control(lb); -} - -int ListBoxImpl::GetSelection() { -    Handle selectedItems = NewHandle(0); -    GetDataBrowserItems(lb, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems); -    UInt32 numSelectedItems = GetHandleSize(selectedItems)/sizeof(DataBrowserItemID); -    if (numSelectedItems == 0) { -        return -1; -    } -    HLock( selectedItems ); -    DataBrowserItemID *individualItem = (DataBrowserItemID*)( *selectedItems ); -    DataBrowserItemID selected[numSelectedItems]; -    selected[0] = *individualItem; -    HUnlock( selectedItems ); -    return selected[0] - 1; -} - -int ListBoxImpl::Find(const char *prefix) { -    int count = Length(); -    char s[255]; -    for (int i = 0; i < count; i++) { -        GetValue(i, s, 255); -        if (s[0] != NULL && (0 == strncmp(prefix, s, strlen(prefix)))) { -            return i; -        } -    } -    return - 1; -} - -void ListBoxImpl::GetValue(int n, char *value, int len) { -    CFStringRef textString = ld.GetString(n); -    if (textString == NULL) { -        value[0] = '\0'; -        return; -    } -    CFIndex numUniChars = CFStringGetLength( textString ); - -    // XXX how do we know the encoding of the listbox? -    CFStringEncoding encoding = kCFStringEncodingUTF8; //( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); -    CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; -    char* text = new char[maximumByteLength]; -    CFIndex usedBufferLength = 0; -    CFStringGetBytes( textString, CFRangeMake( 0, numUniChars ), encoding, -              '?', false, reinterpret_cast<UInt8*>( text ), -              maximumByteLength, &usedBufferLength ); -    text[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string - -    if (text && len > 0) { -        strncpy(value, text, len); -        value[len - 1] = '\0'; -    } else { -        value[0] = '\0'; -    } -    delete []text; -} - -void ListBoxImpl::RegisterImage(int type, const char *xpm_data) { -    xset.Add(type, xpm_data); -} - -void ListBoxImpl::RegisterRGBAImage(int /* type */, int /* width */, int /* height */, const unsigned char * /*pixelsImage */) { -	// Not supported for Carbon -} - -void ListBoxImpl::ClearRegisteredImages() { -    xset.Clear(); -} - -Menu::Menu() : mid(0) { } - -void Menu::CreatePopUp() { -    // TODO: Could I just feed a constant menu ID parameter, or does -    // it really need to be unique? -    static int nextMenuID = 1; -    Destroy(); -    OSStatus err; -    err = CreateNewMenu( nextMenuID++, 0, reinterpret_cast<MenuRef*>( &mid ) ); -} - -void Menu::Destroy() { -    if ( mid != NULL ) -    { -        ReleaseMenu( reinterpret_cast<MenuRef>( mid ) ); -        mid = NULL; -    } -} - -void Menu::Show(Point pt, Window &) { -    UInt32 userSelection = 0; -    SInt16 menuId = 0; -    MenuItemIndex menuItem = 0; -    ::Point globalPoint; -    globalPoint.h = pt.x; -    globalPoint.v = pt.y; -    OSStatus err; -    err = ContextualMenuSelect( reinterpret_cast<MenuRef>( mid ), globalPoint, -                                false, kCMHelpItemRemoveHelp, NULL, -                                NULL, &userSelection, -                                &menuId, -                                &menuItem -                                ); -} - -// ElapsedTime is used for precise performance measurements during development -// and not for anything a user sees. - -ElapsedTime::ElapsedTime() { -    struct timeval curTime; -    int retVal; -    retVal = gettimeofday( &curTime, NULL ); - -    bigBit = curTime.tv_sec; -    littleBit = curTime.tv_usec; -} - -double ElapsedTime::Duration(bool reset) { -    struct timeval curTime; -    int retVal; -    retVal = gettimeofday( &curTime, NULL ); -    long endBigBit = curTime.tv_sec; -    long endLittleBit = curTime.tv_usec; -    double result = 1000000.0 * (endBigBit - bigBit); -    result += endLittleBit - littleBit; -    result /= 1000000.0; -    if (reset) { -        bigBit = endBigBit; -        littleBit = endLittleBit; -    } -    return result; -} - -ColourDesired Platform::Chrome() { -    RGBColor c; -    GetThemeBrushAsColor(kThemeBrushButtonActiveDarkShadow , 24, true, &c); -    return ColourDesired(c.red>>8, c.green>>8, c.blue>>8); -} - -ColourDesired Platform::ChromeHighlight() { -    RGBColor c; -    GetThemeBrushAsColor(kThemeBrushButtonInactiveLightShadow , 24, true, &c); -    return ColourDesired(c.red>>8, c.green>>8, c.blue>>8); -} - -static Str255 PlatformDefaultFontName; -const char *Platform::DefaultFont() { -    long fid = HighShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize)); -    FMGetFontFamilyName(fid, PlatformDefaultFontName); -    char* defaultFontName = (char*) PlatformDefaultFontName; -    defaultFontName[defaultFontName[0]+1] = 0; -    ++defaultFontName; - -    return defaultFontName; -} - -int Platform::DefaultFontSize() { -    return LowShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize)); -} - -unsigned int Platform::DoubleClickTime() { -    // Convert from ticks to milliseconds. I think it would be better to use the events to tell us -    // when we have a double and triple click, but what do I know? -    return static_cast<unsigned int>( TicksToEventTime( GetDblTime() ) / kEventDurationMillisecond ); -} - -bool Platform::MouseButtonBounce() { -    return false; -} - -bool Platform::IsKeyDown(int keyCode) { -    return false; -    // TODO: Map Scintilla/Windows key codes to Mac OS X key codes -    // TODO: Do I need this? -    /* -    // Inspired by code at: http://www.sover.net/~jams/Morgan/docs/GameInputMethods.txt - -    // Get the keys -    KeyMap keys; -    GetKeys( keys ); - -    // Calculate the key map index -    long keyMapIndex = keys[keyCode/8]; -    // Calculate the individual bit to check -    short bitToCheck = keyCode % 8; -    // Check the status of the key -    return ( keyMapIndex >> bitToCheck ) & 0x01; -     */ -} - -long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) { -    return scintilla_send_message( w, msg, wParam, lParam ); -} - -bool Platform::IsDBCSLeadByte(int /*codePage*/, char /*ch*/) { -    // TODO: Implement this for code pages != UTF-8 -    return false; -} - -int Platform::DBCSCharLength(int /*codePage*/, const char* /*s*/) { -    // TODO: Implement this for code pages != UTF-8 -    return 1; -} - -int Platform::DBCSCharMaxLength() { -    // TODO: Implement this for code pages != UTF-8 -    //return CFStringGetMaximumSizeForEncoding( 1, CFStringEncoding encoding ); -    return 2; -} - -// These are utility functions not really tied to a platform -int Platform::Minimum(int a, int b) { -    if (a < b) -        return a; -    else -        return b; -} - -int Platform::Maximum(int a, int b) { -    if (a > b) -        return a; -    else -        return b; -} - -//#define TRACE -#ifdef TRACE - -void Platform::DebugDisplay(const char *s) { -    fprintf( stderr, s ); -} - -void Platform::DebugPrintf(const char *format, ...) { -    const int BUF_SIZE = 2000; -    char buffer[BUF_SIZE]; - -    va_list pArguments; -    va_start(pArguments, format); -    vsnprintf(buffer, BUF_SIZE, format, pArguments); -    va_end(pArguments); -    Platform::DebugDisplay(buffer); -} - -#else - -void Platform::DebugDisplay(const char *) {} - -void Platform::DebugPrintf(const char *, ...) {} - -#endif - -// Not supported for GTK+ -static bool assertionPopUps = true; - -bool Platform::ShowAssertionPopUps(bool assertionPopUps_) { -    bool ret = assertionPopUps; -    assertionPopUps = assertionPopUps_; -    return ret; -} - -void Platform::Assert(const char *c, const char *file, int line) { -    char buffer[2000]; -    sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); -    strcat(buffer, "\r\n"); -    Platform::DebugDisplay(buffer); -#ifdef DEBUG -    // Jump into debugger in assert on Mac (CL269835) -    ::Debugger(); -#endif -} - -int Platform::Clamp(int val, int minVal, int maxVal) { -    if (val > maxVal) -        val = maxVal; -    if (val < minVal) -        val = minVal; -    return val; -} | 
