diff options
Diffstat (limited to 'macosx')
| -rw-r--r-- | macosx/PlatMacOSX.cxx | 1922 | ||||
| -rw-r--r-- | macosx/PlatMacOSX.h | 101 | ||||
| -rw-r--r-- | macosx/QuartzTextLayout.h | 130 | ||||
| -rw-r--r-- | macosx/QuartzTextStyle.h | 105 | ||||
| -rw-r--r-- | macosx/QuartzTextStyleAttribute.h | 146 | ||||
| -rw-r--r-- | macosx/SciTest/English.lproj/InfoPlist.strings | bin | 0 -> 256 bytes | |||
| -rw-r--r-- | macosx/SciTest/Info.plist | 24 | ||||
| -rw-r--r-- | macosx/SciTest/SciTest.xcode/project.pbxproj | 287 | ||||
| -rw-r--r-- | macosx/SciTest/SciTest_Prefix.pch | 5 | ||||
| -rw-r--r-- | macosx/SciTest/main.cpp | 225 | ||||
| -rw-r--r-- | macosx/SciTest/version.plist | 16 | ||||
| -rw-r--r-- | macosx/ScintillaCallTip.cxx | 117 | ||||
| -rw-r--r-- | macosx/ScintillaCallTip.h | 64 | ||||
| -rw-r--r-- | macosx/ScintillaListBox.cxx | 103 | ||||
| -rw-r--r-- | macosx/ScintillaListBox.h | 63 | ||||
| -rw-r--r-- | macosx/ScintillaMacOSX.cxx | 2118 | ||||
| -rw-r--r-- | macosx/ScintillaMacOSX.h | 192 | ||||
| -rw-r--r-- | macosx/TCarbonEvent.cxx | 519 | ||||
| -rw-r--r-- | macosx/TCarbonEvent.h | 230 | ||||
| -rw-r--r-- | macosx/TRect.h | 496 | ||||
| -rw-r--r-- | macosx/TView.cxx | 1462 | ||||
| -rw-r--r-- | macosx/TView.h | 286 | ||||
| -rw-r--r-- | macosx/deps.mak | 315 | ||||
| -rw-r--r-- | macosx/makefile | 95 | 
24 files changed, 9021 insertions, 0 deletions
| diff --git a/macosx/PlatMacOSX.cxx b/macosx/PlatMacOSX.cxx new file mode 100644 index 000000000..149b99ceb --- /dev/null +++ b/macosx/PlatMacOSX.cxx @@ -0,0 +1,1922 @@ +// 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 <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() : id(0) {} + +Font::~Font() { Release(); } + + +void Font::Create(const char *faceName, int /*characterSet*/, +                  int size, bool bold, bool italic, bool /*extraFontFlag*/) { +    // TODO: How should I handle the characterSet request? +    Release(); + +    id = 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*>( id )->setAttributes( attributes, sizeof( attributes ) / sizeof( *attributes ) ); + +    //ATSStyleRenderingOptions rendering = kATSStyleNoAntiAliasing; +    //reinterpret_cast<QuartzTextStyle*>( id )->setAttribute( kATSUStyleRenderingOptionsTag, sizeof( rendering ), &rendering ); + +    // TODO: Why do I have to manually set this? +    reinterpret_cast<QuartzTextStyle*>( id )->setFontFeature( kLigaturesType, kCommonLigaturesOffSelector ); +} + +void Font::Release() { +    if (id) +            delete reinterpret_cast<QuartzTextStyle*>( id ); + +    id = 0; +} + +SurfaceImpl::SurfaceImpl() { +    bitmapData = NULL; // Release will try and delete bitmapData if != NULL +#ifdef SUPPORT_PORT +    port = NULL; +#endif +    gc = NULL; +    Release(); +} + +SurfaceImpl::~SurfaceImpl() { +    Release(); +} + +void SurfaceImpl::Release() { +    if ( bitmapData != NULL ) +        { +        delete[] bitmapData; +        // We only "own" the graphics context if we are a bitmap context +        if ( gc != NULL ) CGContextRelease( gc ); +        } +#ifdef SUPPORT_PORT +    if ( port != NULL && gc != NULL) { +      QDEndCGContext(port, &gc); +    } +#endif +    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(); +#ifdef SUPPORT_PORT +    // Note, this seems to be unecessary, I have not seen any functionality loss by +    // doing nothing in this method. + +    WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>(wid)); +    port = GetWindowPort(window); +    QDBeginCGContext(port, &gc); +#endif +} + +void SurfaceImpl::Init(SurfaceID sid, WindowID /*wid*/) { +    Release(); +    gc = reinterpret_cast<CGContextRef>( sid ); +    CGContextSetLineWidth( gc, 1.0 ); +} + +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(); +    assert( colorSpace != NULL ); + +    // create the bitmap +    bitmapData = new uint8_t[ bitmapByteCount ]; +    assert( bitmapData != NULL ); +    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; +            } +        } + +    // the context retains the color space, so we can release it +    CGColorSpaceRelease( colorSpace );   + +    assert( 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(); +    assert( colorSpace != 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 ); +    assert( dataProvider != NULL ); + +    // create the CGImage +    CGImageRef image = CGImageCreate( bitmapWidth, +                                   bitmapHeight, +                                   BITS_PER_COMPONENT, +                                   BITS_PER_PIXEL, +                                   bitmapBytesPerRow, +                                   colorSpace, +                                   kCGImageAlphaPremultipliedLast, +                                   dataProvider, +                                   NULL, +                                   0, +                                   kCGRenderingIntentDefault ); +    assert( image != NULL ); + +    // 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 ); +    // TODO: Should the path be automatically closed, or is that the caller's responsability? +    // 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. +        // TODO: Create some version of PRectangleToCGRect to do this conversion for us? +        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; +        } + +    assert( image != NULL ); + +    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 +                                         ); +    assert( pattern != NULL ); + +    // Create a pattern color space +    CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); +    assert( 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; +    CGPatternRelease( pattern ); +    pattern = NULL; +    CGImageRelease( image ); +    image = NULL; +} + +void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { +    // TODO: Look at the Win32 API to determine what this is supposed to do: +    //  ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 ); +     +    // 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 +    // TODO: Should I include these +0.5 in the array creation code above? +    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 SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, +        ColourAllocated outline, int alphaOutline, int flags) { +    // XXX TODO +    if ( gc ) { +        CGContextBeginPath( gc ); +        //FillColour(fill); +        PenColour(outline); + +        // 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. +        // TODO: Create some version of PRectangleToCGRect to do this conversion for us? +        CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) ); +        CGContextDrawPath( gc, kCGPathFill ); +    } +} + +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; +        } +     +    assert( image != NULL ); + +    // 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; +} + +QuartzTextLayout* SurfaceImpl::GetTextLayout( Font &font_, const char *s, int len ) +{ +    // create the text layout +    QuartzTextLayout* textLayout = new QuartzTextLayout( gc ); +    OSStatus err = textLayout->setText( reinterpret_cast<const UInt8*>( s ), len, ( unicodeMode ? kCFStringEncodingUTF8 : kCFStringEncodingASCII ) ); +    if (err != noErr) { +        fprintf(stderr, "SurfaceImpl::GetTextLayout error calling textLayout->setText %d %s\n", err, unicodeMode?"Invalid UTF8":"Unknown error"); +        if (unicodeMode) +            err = textLayout->setText( reinterpret_cast<const UInt8*>( s ), len, kCFStringEncodingASCII ); +        if (err != noErr)  +            return NULL; +    } +     +    textLayout->setStyle( *reinterpret_cast<QuartzTextStyle*>( font_.GetID() ) ); + +    // TODO: If I could modify Scintilla to use ATSUHighlightText, this would not be required. +    // However, using this setting makes Scintilla's rendering match TextEdit's (except for the antialiasing rules) +    ATSLineLayoutOptions rendering = kATSLineUseDeviceMetrics; +    textLayout->setControl( kATSULineLayoutOptionsTag, sizeof( rendering ), &rendering ); + +    return textLayout; +} + +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) { +    PLATFORM_ASSERT( gc != NULL ); +    QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); +    if (!textLayout) return; +    // 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 ); + +    // Get rid of the layout object +    delete textLayout; +    textLayout = NULL; +} + +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. +    QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); +    if (!textLayout) return; + +    // Get the UNICODE character length +    UniCharCount unicodeLength, unicodePosition; +    OSStatus err; +    err = ATSUGetTextLocation( textLayout->getLayout(), NULL, NULL, NULL, &unicodeLength, NULL ); +    assert( err == noErr ); + +    ATSLayoutRecord *layoutRecords; +    ItemCount numRecords; +    // Get the arrays of glyph information +    verify_noerr( ATSUDirectGetLayoutDataArrayPtrFromTextLayout( +                textLayout->getLayout(), 0, +                kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, +                (void **)&layoutRecords, &numRecords) ); +     +    int i, count; +    long position; +    unsigned char uch; +    unsigned char mask; +    FontID fontid = font_.GetID(); +     +    for ( unicodePosition = 0, i = 0; i < len && unicodePosition < numRecords; unicodePosition ++ ) { +        if (fontid) { + +            // note: an extra layoutRecord is provided (eg. numRecords will be one +            //       more than unicodeLength).  Each record contains the left x +            //       coordinate, but we need the right x coordinate, so we skip +            //       the first layoutRecord, thus unicodePosition+1. +            position = Fix2Long( layoutRecords[unicodePosition+1].realPos ); +            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 ) { +                mask = 0xc0; +                count = 1; +                // Add one additonal byte for each extra high order one in the byte +                while ( uch >= mask && count < 8 ) { +                    assert( i < len ); +                    positions[i++] = position; +                    count ++; +                    mask = mask >> 1 | 0x80; // add an additional one in the highest order position +                } +                assert( count <= 8 ); +            } +        } else { +        positions[i++] = (i == 0) ? 1 : positions[i-1] + 1; +        } +    } +    verify_noerr( ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords) ); +    // Get rid of the layout object +    delete textLayout; +    textLayout = NULL; +} + +int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { +    if (font_.GetID()) +    { +        QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); +        if (!textLayout) return 0; +         +        // 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" ); +            // Get rid of the layout object +            delete textLayout; +            textLayout = NULL; +            return 0; +        } + +        //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) ); +         +        // Get rid of the layout object +        delete textLayout; +        textLayout = NULL; +        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()) +    { +        QuartzTextLayout* textLayout = GetTextLayout( font_, str, 1 ); +        if (!textLayout) return 0; + +        // 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" ); +            // Get rid of the layout object +            delete textLayout; +            textLayout = NULL; +            return 0; +        } + +        // Get rid of the layout object +        delete textLayout; +        textLayout = NULL; +        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 +} + +Surface *Surface::Allocate() { +    return new SurfaceImpl(  ); +} + +Window::~Window() {} + +void Window::Destroy() { +    if (windowRef) { +        DisposeWindow(reinterpret_cast<WindowRef>( windowRef )); +    } +    id = 0; +} + +bool Window::HasFocus() { +    // TODO: Test this +    return HIViewSubtreeContainsFocus( reinterpret_cast<HIViewRef>( id ) ); +} + +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 (id) { +        HIRect controlFrame; +        HIViewGetFrame( reinterpret_cast<HIViewRef>( id ), &controlFrame ); +        rc = CGRectToPRectangle( controlFrame ); +    } +     +    return rc; +} + +void Window::SetPosition(PRectangle rc) { +    // Moves this view inside the parent view +    if ( id ) +    { +        // Set the frame on the view, the function handles the rest +        CGRect r = PRectangleToCGRect( rc ); +        HIViewSetFrame( reinterpret_cast<HIViewRef>( id ), &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 ( id ) { +        HIViewSetVisible( reinterpret_cast<HIViewRef>( id ), 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 ( id ) { +        OSStatus err; +        err = HIViewSetNeedsDisplay( reinterpret_cast<HIViewRef>( id ), true ); +        assert( err == noErr ); +    } +} + +void Window::InvalidateRectangle(PRectangle rc) { +    if (id) { +        // Create a rectangular region +        RgnHandle region = NewRgn(); +        assert( region != NULL ); +        SetRectRgn( region, rc.left, rc.top, rc.right, rc.bottom ); + +        // Make that region invalid +        OSStatus err; +        err = HIViewSetNeedsDisplayInRegion( reinterpret_cast<HIViewRef>( id ), region, true ); +        assert( err == noErr ); +        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 (id) { +        // 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: +            case cursorReverseArrow: +            case cursorUp: +            default: +                cursor = kThemeArrowCursor; +                break; +        } +         +        SetThemeCursor( cursor ); +    } +} + +void Window::SetTitle(const char *s) { +    WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>( id )); +    CFStringRef title = CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingMacRoman); +    SetWindowTitleWithCFString(window, title); +    CFRelease(title); +} + +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 maxItemCharacters; +    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), maxItemCharacters(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 Sort(); +    void RegisterImage(int type, const char *xpm_data); +    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 = 1000; +     +    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 ); + +    id = 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 fontName; +    if (FMGetFontFamilyName(style.font, fontName) != kFMInvalidFontFamilyErr) { +      // make sure we conver to a proper C string first. +      char cFontName[255]; +      CopyPascalStringToC(fontName, cFontName); +      font.Create((const char *)cFontName, 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; +    int width = maxItemCharacters; +    if (width < 12) +        width = 12; +    // XXX use the quartz text stuff to figure out the correct string width +    rcDesired.right = rcDesired.left + width * (aveCharWidth+aveCharWidth/4); +    if (rcDesired.right > maxWidth) { +        rcDesired.right = maxWidth; +    } +    if (Length() > rows)  +        rcDesired.right += kScrollBarWidth; +    rcDesired.right += IconWidth(); +    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 +    maxItemCharacters = 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); +   +    DataBrowserItemID items[1]; +    items[0] = count + 1; +    AddDataBrowserItems (lb, kDataBrowserNoItem, 1, items, kDataBrowserItemNoProperty); +    ShowHideScrollbar(); +     +    size_t len = strlen(s); +    if (maxItemCharacters < len) +            maxItemCharacters = len; + +} + +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::Sort() { +    // TODO: Implement this +    fprintf(stderr, "ListBox::Sort\n"); +} + +void ListBoxImpl::RegisterImage(int type, const char *xpm_data) { +    xset.Add(type, xpm_data); +} + +void ListBoxImpl::ClearRegisteredImages() { +    xset.Clear(); +} + +Menu::Menu() : id(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*>( &id ) ); +    assert( noErr == err && id != NULL ); +} + +void Menu::Destroy() { +    if ( id != NULL ) +    { +        ReleaseMenu( reinterpret_cast<MenuRef>( id ) ); +        id = 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>( id ), globalPoint, +                                false, kCMHelpItemRemoveHelp, NULL, +                                NULL, &userSelection, +                                &menuId, +                                &menuItem +                                ); +    // The system should always handle the command for us, so we should get userCanceledErr +    assert( /*noErr == err ||*/ userCanceledErr == err ); +} + +// TODO: Consider if I should be using GetCurrentEventTime instead of gettimeoday +ElapsedTime::ElapsedTime() { +    struct timeval curTime; +    int retVal; +    retVal = gettimeofday( &curTime, NULL ); +    assert( retVal == 0 ); +     +    bigBit = curTime.tv_sec; +    littleBit = curTime.tv_usec; +} + +double ElapsedTime::Duration(bool reset) { +    struct timeval curTime; +    int retVal; +    retVal = gettimeofday( &curTime, NULL ); +    assert( retVal == 0 ); +    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 id = HighShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize)); +    FMGetFontFamilyName(id, PlatformDefaultFontName); +    return (const char *)PlatformDefaultFontName; +} + +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::WaitMouseMoved(Scintilla::Point pt) {  +    ::Point mpt; +    mpt.v = pt.x; +    mpt.h = pt.y; +    return ::WaitMouseMoved(mpt); +} + +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 +    return false; +} + +int Platform::DBCSCharLength(int /*codePage*/, const char* /*s*/) { +    // TODO: Implement this +    return 1; +} + +int Platform::DBCSCharMaxLength() { +    // TODO: Implement this +    //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); +    abort(); +} + +int Platform::Clamp(int val, int minVal, int maxVal) { +    assert( minVal <= maxVal ); +    if (val > maxVal) +        val = maxVal; +    if (val < minVal) +        val = minVal; +    return val; +} diff --git a/macosx/PlatMacOSX.h b/macosx/PlatMacOSX.h new file mode 100644 index 000000000..168ba74ee --- /dev/null +++ b/macosx/PlatMacOSX.h @@ -0,0 +1,101 @@ +#ifndef PLATMACOSX_H +#define PLATMACOSX_H + +#include <cstring> +#include <cstdio> +#include <cstdlib> + +#include <assert.h> + +#include <sys/time.h> + +#include <Carbon/Carbon.h> +#include "QuartzTextLayout.h" + +#include "Platform.h" +#include "Scintilla.h" + +namespace Scintilla { + +class SurfaceImpl : public Surface { +private: +    bool unicodeMode; +    float x; +    float y; + +#ifdef SUPPORT_PORT +    CGrafPtr port; +#endif +    CGContextRef gc; + + +    /** If the surface is a bitmap context, contains a reference to the bitmap data. */ +    uint8_t* bitmapData; +    /** If the surface is a bitmap context, stores the dimensions of the bitmap. */ +    int bitmapWidth; +    int bitmapHeight; + +    /** Set the CGContext's fill colour to the specified allocated colour. */ +    void FillColour( const ColourAllocated& back ); + + +    // 24-bit RGB+A bitmap data constants +    static const int BITS_PER_COMPONENT = 8; +    static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4; +    static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8; +public: +    SurfaceImpl(); +    ~SurfaceImpl(); + +    void Init(WindowID wid); +    void Init(SurfaceID sid, WindowID wid); +    void InitPixMap(int width, int height, Surface *surface_, WindowID wid); +    CGContextRef GetContext() { return gc; } + +    void Release(); +    bool Initialised(); +    void PenColour(ColourAllocated fore); + +    /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */ +    CGImageRef GetImage(); +    void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect); + +    int LogPixelsY(); +    int DeviceHeightFont(int points); +    void MoveTo(int x_, int y_); +    void LineTo(int x_, int y_); +    void Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore, ColourAllocated back); +    void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back); +    void FillRectangle(PRectangle rc, ColourAllocated back); +    void FillRectangle(PRectangle rc, Surface &surfacePattern); +    void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back); +    void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, +            ColourAllocated outline, int alphaOutline, int flags); +    void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); +    void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource); + +    QuartzTextLayout* GetTextLayout( Font &font_, const char *s, int len ); +    void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); +    void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); +    void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore); +    void MeasureWidths(Font &font_, const char *s, int len, int *positions); +    int WidthText(Font &font_, const char *s, int len); +    int WidthChar(Font &font_, char ch); +    int Ascent(Font &font_); +    int Descent(Font &font_); +    int InternalLeading(Font &font_); +    int ExternalLeading(Font &font_); +    int Height(Font &font_); +    int AverageCharWidth(Font &font_); + +    int SetPalette(Scintilla::Palette *pal, bool inBackGround); +    void SetClip(PRectangle rc); +    void FlushCachedState(); + +    void SetUnicodeMode(bool unicodeMode_); +    void SetDBCSMode(int codePage); +}; + +} + +#endif diff --git a/macosx/QuartzTextLayout.h b/macosx/QuartzTextLayout.h new file mode 100644 index 000000000..1461a078f --- /dev/null +++ b/macosx/QuartzTextLayout.h @@ -0,0 +1,130 @@ +/* + *  QuartzTextLayout.h + *  wtf + * + *  Created by Evan Jones on Wed Oct 02 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef _QUARTZ_TEXT_LAYOUT_H +#define _QUARTZ_TEXT_LAYOUT_H + +#include <Carbon/Carbon.h> + +#include "QuartzTextStyle.h" + +class QuartzTextLayout +{ +public: +    /** Create a text layout for drawing on the specified context. */ +    QuartzTextLayout( CGContextRef context ) : layout( NULL ), unicode_string( NULL ), unicode_length( 0 ) +    { +        gc = context; + +        OSStatus err; +        err = ATSUCreateTextLayout( &layout ); +        assert( err == noErr && layout != NULL ); + +        setControl( kATSUCGContextTag, sizeof( gc ), &gc ); + +        /*ATSUAttributeTag tag = kATSULineLayoutOptionsTag; +        ByteCount size = sizeof( ATSLineLayoutOptions ); +        ATSLineLayoutOptions rendering = kATSLineHasNoOpticalAlignment; // kATSLineUseDeviceMetrics; | kATSLineFractDisable | kATSLineUseQDRendering +        ATSUAttributeValuePtr valuePtr = &rendering; +        err = ATSUSetLayoutControls( layout, 1, &tag, &size, &valuePtr ); +        assert( err == noErr );*/ +    } + +    ~QuartzTextLayout() +    { +        assert( layout != NULL ); +        ATSUDisposeTextLayout( layout ); +        layout = NULL; + +        if ( unicode_string != NULL ) +        { +            delete[] unicode_string; +            unicode_string = NULL; +            unicode_length = 0; +        } +    } + +    /** Assign a string to the text layout object. */ +    // TODO: Create a UTF8 version +    // TODO: Optimise the ASCII version by not copying so much +    OSStatus setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding ) +    { +        assert( buffer != NULL && byteLength > 0 ); +         +        CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false ); +        if (!str) +            return -1; + +        unicode_length = CFStringGetLength( str ); +        unicode_string = new UniChar[ unicode_length ]; +        CFStringGetCharacters( str, CFRangeMake( 0, unicode_length ), unicode_string ); + +        CFRelease( str ); +        str = NULL; + +        OSStatus err; +        err = ATSUSetTextPointerLocation( layout, unicode_string, kATSUFromTextBeginning, kATSUToTextEnd, unicode_length ); +        if( err != noErr ) return err; + +        // Turn on the default font fallbacks +        return ATSUSetTransientFontMatching( layout, true ); +    } + +    /** Apply the specified text style on the entire range of text. */ +    void setStyle( const QuartzTextStyle& style ) +    { +        OSStatus err; +        err = ATSUSetRunStyle( layout, style.getATSUStyle(), kATSUFromTextBeginning, kATSUToTextEnd ); +        assert( err == noErr ); +    } + +    /** Draw the text layout into the current CGContext at the specified position, flipping the CGContext's Y axis if required. +    * @param x The x axis position to draw the baseline in the current CGContext. +    * @param y The y axis position to draw the baseline in the current CGContext. +    * @param flipTextYAxis If true, the CGContext's Y axis will be flipped before drawing the text, and restored afterwards. Use this when drawing in an HIView's CGContext, where the origin is the top left corner. */ +    void draw( float x, float y, bool flipTextYAxis = false ) +    { +        if ( flipTextYAxis ) +        { +            CGContextSaveGState( gc ); +            CGContextScaleCTM( gc, 1.0, -1.0 ); +            y = -y; +        } +         +        OSStatus err; +        err = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) ); +        assert( err == noErr ); + +        if ( flipTextYAxis ) CGContextRestoreGState( gc ); +    } + +    /** Sets a single text layout control on the ATSUTextLayout object. +    * @param tag The control to set. +    * @param size The size of the parameter pointed to by value. +    * @param value A pointer to the new value for the control. +    */ +    void setControl( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value ) +    { +        OSStatus err; +        err = ATSUSetLayoutControls( layout, 1, &tag, &size, &value ); +        assert( noErr == err ); +    } + +    ATSUTextLayout getLayout() { +        return layout; +    } + +private: +    ATSUTextLayout layout; +    UniChar* unicode_string; +    int unicode_length; +    CGContextRef gc; +}; + +#endif diff --git a/macosx/QuartzTextStyle.h b/macosx/QuartzTextStyle.h new file mode 100644 index 000000000..d3a5db5dc --- /dev/null +++ b/macosx/QuartzTextStyle.h @@ -0,0 +1,105 @@ +/* + *  QuartzTextStyle.h + *  wtf + * + *  Created by Evan Jones on Wed Oct 02 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ + +#include <Carbon/Carbon.h> + +#ifndef _QUARTZ_TEXT_STYLE_H +#define _QUARTZ_TEXT_STYLE_H + +#include "QuartzTextStyleAttribute.h" + +class QuartzTextStyle +{ +public: +    QuartzTextStyle() +    { +        OSStatus err; +        err = ATSUCreateStyle( &style ); +        assert( err == noErr ); +    } + +    ~QuartzTextStyle() +    { +        assert( style != NULL ); +        ATSUDisposeStyle( style ); +        style = NULL; +    } + +    void setAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value ) +    { +        OSStatus err; +        err = ATSUSetAttributes( style, 1, &tag, &size, &value ); +        assert( err == noErr ); +    } + +    void setAttribute( QuartzTextStyleAttribute& attribute ) +    { +        setAttribute( attribute.getTag(), attribute.getSize(), attribute.getValuePtr() ); +    } + +    void getAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value, ByteCount* actualSize ) +    { +        OSStatus err; err = ATSUGetAttribute( style, tag, size, value, actualSize ); +        assert( err == noErr ); +    } + +    template <class T> +    T getAttribute( ATSUAttributeTag tag ) +    { +        T value; +        ByteCount actualSize; +        OSStatus err; +        err = ATSUGetAttribute( style, tag, sizeof( T ), &value, &actualSize ); +        assert( (err == noErr || err == kATSUNotSetErr) && actualSize == sizeof( T ) ); +        return value; +    } + +    // TODO: Is calling this actually faster than calling setAttribute multiple times? +    void setAttributes( QuartzTextStyleAttribute* attributes[], int number ) +    { +        // Create the parallel arrays and initialize them properly +        ATSUAttributeTag* tags = new ATSUAttributeTag[ number ]; +        ByteCount* sizes = new ByteCount[ number ]; +        ATSUAttributeValuePtr* values = new ATSUAttributeValuePtr[ number ]; + +        for ( int i = 0; i < number; ++ i ) +        { +            tags[i] = attributes[i]->getTag(); +            sizes[i] = attributes[i]->getSize(); +            values[i] = attributes[i]->getValuePtr(); +        } +         +        OSStatus err; +        err = ATSUSetAttributes( style, number, tags, sizes, values ); +        //assert( err == noErr ); + +        // Free the arrays that were allocated +        delete[] tags; +        delete[] sizes; +        delete[] values; +    } + +    void setFontFeature( ATSUFontFeatureType featureType, ATSUFontFeatureSelector selector ) +    { +        OSStatus err; +        err = ATSUSetFontFeatures( style, 1, &featureType, &selector ); +        assert( err == noErr ); +    } + +    const ATSUStyle& getATSUStyle() const +    { +        return style; +    } + +private: +    ATSUStyle style; +}; + +#endif + diff --git a/macosx/QuartzTextStyleAttribute.h b/macosx/QuartzTextStyleAttribute.h new file mode 100644 index 000000000..490ef7d02 --- /dev/null +++ b/macosx/QuartzTextStyleAttribute.h @@ -0,0 +1,146 @@ +/* + *  QuartzTextStyleAttribute.h + *  wtf + * + *  Created by Evan Jones on Wed Oct 02 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ + + +#include <Carbon/Carbon.h> + +#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H +#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H + +class QuartzTextStyleAttribute +{ +public: +    virtual ByteCount getSize() const = 0; +    virtual ATSUAttributeValuePtr getValuePtr() = 0; +    virtual ATSUAttributeTag getTag() const = 0; +}; + +class QuartzTextSize : public QuartzTextStyleAttribute +{ +public:  +    QuartzTextSize( float points ) +    { +        size = X2Fix( points ); +    } +     +    ByteCount getSize() const +    { +        return sizeof( size ); +    } + +    ATSUAttributeValuePtr getValuePtr() +    { +        return &size; +    } + +    ATSUAttributeTag getTag() const +    { +        return kATSUSizeTag; +    } +     +private: +        Fixed size; +}; + +class QuartzTextStyleAttributeBoolean : public QuartzTextStyleAttribute +{ +public: +    QuartzTextStyleAttributeBoolean( bool newVal ) : value( newVal ) {} + +    ByteCount getSize() const +    { +        return sizeof( value ); +    } +    ATSUAttributeValuePtr getValuePtr() +    { +        return &value; +    } +     +    virtual ATSUAttributeTag getTag() const = 0; +     +private: +        Boolean value; +}; + +class QuartzTextBold : public QuartzTextStyleAttributeBoolean +{ +public: +    QuartzTextBold( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {} +    ATSUAttributeTag getTag() const +    { +        return kATSUQDBoldfaceTag; +    } +}; + +class QuartzTextItalic : public QuartzTextStyleAttributeBoolean +{ +public: +    QuartzTextItalic( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {} +    ATSUAttributeTag getTag() const +    { +        return kATSUQDItalicTag; +    } +}; + +class QuartzTextUnderline : public QuartzTextStyleAttributeBoolean +{ +public: +    QuartzTextUnderline( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {} +    ATSUAttributeTag getTag() const { +        return kATSUQDUnderlineTag; +    } +}; + +class QuartzFont : public QuartzTextStyleAttribute +{ +public: +    /** Create a font style from a name. */ +    QuartzFont( const char* name, int length ) +    { +        assert( name != NULL && length > 0 && name[length] == '\0' ); +        /*CFStringRef fontName = CFStringCreateWithCString( NULL, name, kCFStringEncodingMacRoman ); +         +        ATSFontRef fontRef = ATSFontFindFromName( fontName, kATSOptionFlagsDefault ); +        assert( fontRef != NULL ); +        fontid = fontRef; + +        CFRelease( fontName );*/ + +        OSStatus err; +        err = ATSUFindFontFromName( const_cast<char*>( name ), length, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid ); +        //assert( err == noErr && fontid != kATSUInvalidFontID ); +    } + +    ByteCount getSize() const +    { +        return sizeof( fontid ); +    } + +    ATSUAttributeValuePtr getValuePtr() +    { +        return &fontid; +    } + +    ATSUAttributeTag getTag() const +    { +        return kATSUFontTag; +    } + +    ATSUFontID getFontID() const +    { +        return fontid; +    } + +private: +    ATSUFontID fontid; +}; + + +#endif + diff --git a/macosx/SciTest/English.lproj/InfoPlist.strings b/macosx/SciTest/English.lproj/InfoPlist.stringsBinary files differ new file mode 100644 index 000000000..4dcb4fe03 --- /dev/null +++ b/macosx/SciTest/English.lproj/InfoPlist.strings diff --git a/macosx/SciTest/Info.plist b/macosx/SciTest/Info.plist new file mode 100644 index 000000000..7163dff62 --- /dev/null +++ b/macosx/SciTest/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> +	<key>CFBundleDevelopmentRegion</key> +	<string>English</string> +	<key>CFBundleExecutable</key> +	<string>SciTest</string> +	<key>CFBundleIconFile</key> +	<string></string> +	<key>CFBundleIdentifier</key> +	<string>com.apple.myCarbonApp</string> +	<key>CFBundleInfoDictionaryVersion</key> +	<string>6.0</string> +	<key>CFBundlePackageType</key> +	<string>APPL</string> +	<key>CFBundleSignature</key> +	<string>????</string> +	<key>CFBundleVersion</key> +	<string>1.0</string> +	<key>CSResourcesFileMapped</key> +	<true/> +</dict> +</plist> diff --git a/macosx/SciTest/SciTest.xcode/project.pbxproj b/macosx/SciTest/SciTest.xcode/project.pbxproj new file mode 100644 index 000000000..9ef8fd9bb --- /dev/null +++ b/macosx/SciTest/SciTest.xcode/project.pbxproj @@ -0,0 +1,287 @@ +// !$*UTF8*$! +{ +	archiveVersion = 1; +	classes = { +	}; +	objectVersion = 42; +	objects = { + +/* Begin PBXBuildFile section */ +		3002B123087DCEC600CEAF79 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3002B122087DCEC600CEAF79 /* main.cpp */; }; +		30973FF8086B7F4F0088809C /* libscintilla.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30973FF7086B7F4F0088809C /* libscintilla.a */; }; +		8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; }; +		8D0C4E8E0486CD37000505A6 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; }; +		8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ +		0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; +		1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; }; +		20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; +		3002B122087DCEC600CEAF79 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; +		30973FF7086B7F4F0088809C /* libscintilla.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libscintilla.a; path = ../../bin/libscintilla.a; sourceTree = SOURCE_ROOT; }; +		32DBCF6D0370B57F00C91783 /* SciTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SciTest_Prefix.pch; sourceTree = "<group>"; }; +		4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; }; +		4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; }; +		8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; +		8D0C4E970486CD37000505A6 /* SciTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SciTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ +		8D0C4E910486CD37000505A6 /* Frameworks */ = { +			isa = PBXFrameworksBuildPhase; +			buildActionMask = 2147483647; +			files = ( +				8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, +				30973FF8086B7F4F0088809C /* libscintilla.a in Frameworks */, +			); +			runOnlyForDeploymentPostprocessing = 0; +		}; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ +		195DF8CFFE9D517E11CA2CBB /* Products */ = { +			isa = PBXGroup; +			children = ( +				8D0C4E970486CD37000505A6 /* SciTest.app */, +			); +			name = Products; +			sourceTree = "<group>"; +		}; +		20286C29FDCF999611CA2CEA /* SciTest */ = { +			isa = PBXGroup; +			children = ( +				20286C2AFDCF999611CA2CEA /* Sources */, +				20286C2CFDCF999611CA2CEA /* Resources */, +				20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */, +				195DF8CFFE9D517E11CA2CBB /* Products */, +			); +			name = SciTest; +			sourceTree = "<group>"; +		}; +		20286C2AFDCF999611CA2CEA /* Sources */ = { +			isa = PBXGroup; +			children = ( +				3002B122087DCEC600CEAF79 /* main.cpp */, +				32DBCF6D0370B57F00C91783 /* SciTest_Prefix.pch */, +			); +			name = Sources; +			sourceTree = "<group>"; +		}; +		20286C2CFDCF999611CA2CEA /* Resources */ = { +			isa = PBXGroup; +			children = ( +				8D0C4E960486CD37000505A6 /* Info.plist */, +				0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */, +				02345980000FD03B11CA0E72 /* main.nib */, +			); +			name = Resources; +			sourceTree = "<group>"; +		}; +		20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { +			isa = PBXGroup; +			children = ( +				30973FF7086B7F4F0088809C /* libscintilla.a */, +				20286C33FDCF999611CA2CEA /* Carbon.framework */, +				4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */, +				4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */, +			); +			name = "External Frameworks and Libraries"; +			sourceTree = "<group>"; +		}; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ +		8D0C4E890486CD37000505A6 /* SciTest */ = { +			isa = PBXNativeTarget; +			buildConfigurationList = 304E977D0C0519E500702100 /* Build configuration list for PBXNativeTarget "SciTest" */; +			buildPhases = ( +				8D0C4E8C0486CD37000505A6 /* Resources */, +				8D0C4E8F0486CD37000505A6 /* Sources */, +				8D0C4E910486CD37000505A6 /* Frameworks */, +			); +			buildRules = ( +			); +			dependencies = ( +			); +			name = SciTest; +			productInstallPath = "$(HOME)/Applications"; +			productName = SciTest; +			productReference = 8D0C4E970486CD37000505A6 /* SciTest.app */; +			productType = "com.apple.product-type.application"; +		}; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ +		20286C28FDCF999611CA2CEA /* Project object */ = { +			isa = PBXProject; +			buildConfigurationList = 304E97810C0519E500702100 /* Build configuration list for PBXProject "SciTest" */; +			hasScannedForEncodings = 1; +			mainGroup = 20286C29FDCF999611CA2CEA /* SciTest */; +			projectDirPath = ""; +			targets = ( +				8D0C4E890486CD37000505A6 /* SciTest */, +			); +		}; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ +		8D0C4E8C0486CD37000505A6 /* Resources */ = { +			isa = PBXResourcesBuildPhase; +			buildActionMask = 2147483647; +			files = ( +				8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */, +				8D0C4E8E0486CD37000505A6 /* main.nib in Resources */, +			); +			runOnlyForDeploymentPostprocessing = 0; +		}; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ +		8D0C4E8F0486CD37000505A6 /* Sources */ = { +			isa = PBXSourcesBuildPhase; +			buildActionMask = 2147483647; +			files = ( +				3002B123087DCEC600CEAF79 /* main.cpp in Sources */, +			); +			runOnlyForDeploymentPostprocessing = 0; +		}; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ +		02345980000FD03B11CA0E72 /* main.nib */ = { +			isa = PBXVariantGroup; +			children = ( +				1870340FFE93FCAF11CA0CD7 /* English */, +			); +			name = main.nib; +			sourceTree = "<group>"; +		}; +		0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */ = { +			isa = PBXVariantGroup; +			children = ( +				0867D6ABFE840B52C02AAC07 /* English */, +			); +			name = InfoPlist.strings; +			sourceTree = "<group>"; +		}; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ +		304E977E0C0519E500702100 /* Development */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +				COPY_PHASE_STRIP = NO; +				GCC_DYNAMIC_NO_PIC = NO; +				GCC_ENABLE_FIX_AND_CONTINUE = YES; +				GCC_GENERATE_DEBUGGING_SYMBOLS = YES; +				GCC_OPTIMIZATION_LEVEL = 0; +				GCC_PRECOMPILE_PREFIX_HEADER = YES; +				GCC_PREFIX_HEADER = SciTest_Prefix.pch; +				HEADER_SEARCH_PATHS = ( +					.., +					../../include, +					../../src, +				); +				INFOPLIST_FILE = Info.plist; +				INSTALL_PATH = "$(HOME)/Applications"; +				LIBRARY_SEARCH_PATHS = ../../bin; +				OTHER_CFLAGS = ( +					"-DSCI_NAMESPACE=1", +					"-DSCI_NAMESPACE", +					"-DMACOSX", +					"-DSCI_LEXER", +				); +				OTHER_CPLUSPLUSFLAGS = ( +					"-DSCI_NAMESPACE=1", +					"-DSCI_NAMESPACE", +					"-DMACOSX", +					"-DSCI_LEXER", +				); +				PRODUCT_NAME = SciTest; +				WRAPPER_EXTENSION = app; +				ZERO_LINK = YES; +			}; +			name = Development; +		}; +		304E977F0C0519E500702100 /* Deployment */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +				COPY_PHASE_STRIP = YES; +				GCC_ENABLE_FIX_AND_CONTINUE = NO; +				GCC_GENERATE_DEBUGGING_SYMBOLS = NO; +				GCC_PRECOMPILE_PREFIX_HEADER = YES; +				GCC_PREFIX_HEADER = SciTest_Prefix.pch; +				HEADER_SEARCH_PATHS = ( +					.., +					../../include, +					../../src, +				); +				INFOPLIST_FILE = Info.plist; +				INSTALL_PATH = "$(HOME)/Applications"; +				LIBRARY_SEARCH_PATHS = ""; +				PRODUCT_NAME = SciTest; +				WRAPPER_EXTENSION = app; +				ZERO_LINK = NO; +			}; +			name = Deployment; +		}; +		304E97800C0519E500702100 /* Default */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +				GCC_GENERATE_DEBUGGING_SYMBOLS = NO; +				GCC_PRECOMPILE_PREFIX_HEADER = YES; +				GCC_PREFIX_HEADER = SciTest_Prefix.pch; +				INFOPLIST_FILE = Info.plist; +				INSTALL_PATH = "$(HOME)/Applications"; +				LIBRARY_SEARCH_PATHS = ""; +				PRODUCT_NAME = SciTest; +				WRAPPER_EXTENSION = app; +			}; +			name = Default; +		}; +		304E97820C0519E500702100 /* Development */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +			}; +			name = Development; +		}; +		304E97830C0519E500702100 /* Deployment */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +			}; +			name = Deployment; +		}; +		304E97840C0519E500702100 /* Default */ = { +			isa = XCBuildConfiguration; +			buildSettings = { +			}; +			name = Default; +		}; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ +		304E977D0C0519E500702100 /* Build configuration list for PBXNativeTarget "SciTest" */ = { +			isa = XCConfigurationList; +			buildConfigurations = ( +				304E977E0C0519E500702100 /* Development */, +				304E977F0C0519E500702100 /* Deployment */, +				304E97800C0519E500702100 /* Default */, +			); +			defaultConfigurationIsVisible = 0; +			defaultConfigurationName = Default; +		}; +		304E97810C0519E500702100 /* Build configuration list for PBXProject "SciTest" */ = { +			isa = XCConfigurationList; +			buildConfigurations = ( +				304E97820C0519E500702100 /* Development */, +				304E97830C0519E500702100 /* Deployment */, +				304E97840C0519E500702100 /* Default */, +			); +			defaultConfigurationIsVisible = 0; +			defaultConfigurationName = Default; +		}; +/* End XCConfigurationList section */ +	}; +	rootObject = 20286C28FDCF999611CA2CEA /* Project object */; +} diff --git a/macosx/SciTest/SciTest_Prefix.pch b/macosx/SciTest/SciTest_Prefix.pch new file mode 100644 index 000000000..552cf97fc --- /dev/null +++ b/macosx/SciTest/SciTest_Prefix.pch @@ -0,0 +1,5 @@ +// +// Prefix header for all source files of the 'SciTest' target in the 'SciTest' project. +// + +#include <Carbon/Carbon.h> diff --git a/macosx/SciTest/main.cpp b/macosx/SciTest/main.cpp new file mode 100644 index 000000000..374038005 --- /dev/null +++ b/macosx/SciTest/main.cpp @@ -0,0 +1,225 @@ +//
 +//  main.c
 +//  SciTest
 +//
 +//  Copyright (c) 2005-2006 ActiveState Software Inc.
 +//  All rights reserved.
 +//
 +//  Created by Shane Caraveo on 3/20/05.
 +//
 +
 +#include <Carbon/Carbon.h>
 +#include "TView.h"
 +#include "TCarbonEvent.h"
 +#include "ScintillaMacOSX.h"
 +
 +extern "C" HIViewRef scintilla_new(void);
 +
 +const HILayoutInfo kBindToParentLayout = {
 +  kHILayoutInfoVersionZero,
 +  { { NULL, kHILayoutBindTop }, { NULL, kHILayoutBindLeft }, { NULL, kHILayoutBindBottom }, { NULL, kHILayoutBindRight } },
 +  { { NULL, kHILayoutScaleAbsolute, 0 }, { NULL, kHILayoutScaleAbsolute, 0 } },
 +  { { NULL, kHILayoutPositionTop, 0 }, { NULL, kHILayoutPositionLeft, 0 } }
 +};
 +
 +using namespace Scintilla;
 +
 +/* XPM */
 +static char *ac_class[] = {
 +/* columns rows colors chars-per-pixel */
 +"18 12 24 1",
 +"  c black",
 +". c #403030",
 +"X c #473636",
 +"o c #4E3C3C",
 +"O c #474141",
 +"+ c #5F4C4C",
 +"@ c #756362",
 +"# c #98342C",
 +"$ c #A0392F",
 +"% c #B24235",
 +"& c #B2443C",
 +"* c #B34E3E",
 +"= c #B54E44",
 +"- c #B65146",
 +"; c #B7584F",
 +": c #B8554C",
 +"> c #B75A50",
 +", c #B95852",
 +"< c #B96259",
 +"1 c #B89B9B",
 +"2 c #BCA0A0",
 +"3 c #C1A5A5",
 +"4 c gray100",
 +"5 c None",
 +/* pixels */
 +"555555555555555555",
 +"55553$$$$$$$#@5555",
 +"55552;%&&==;=o5555",
 +"55551>&&*=;:=.5555",
 +"55551>&*=;::=.5555",
 +"55551>*==:::-X5555",
 +"55551>==:::,;.5555",
 +"55551<==:;,<>.5555",
 +"55551<;;;;<<;.5555",
 +"55551;-==;;;;X5555",
 +"55555+XX..X..O5555",
 +"555555555555555555"
 +};
 +
 +pascal OSStatus WindowEventHandler(EventHandlerCallRef	inCallRef,
 +				   EventRef		inEvent,
 +				   void*	        inUserData )
 +{
 +	HIViewRef sciView = *reinterpret_cast<HIViewRef*>( inUserData );
 +	WindowRef window = GetControlOwner(sciView);
 +	ScintillaMacOSX* scintilla;
 +	GetControlProperty( sciView, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
 +	TCarbonEvent event( inEvent );
 +
 +	// If the window is not active, let the standard window handler execute.
 +	if ( ! IsWindowActive( window ) ) return eventNotHandledErr;
 +	
 +	const HIViewRef rootView = HIViewGetRoot( window );
 +	assert( rootView != NULL );
 +
 +	if ( event.GetKind() == kEventMouseDown )
 +		{
 +			UInt32 inKeyModifiers;
 +			event.GetParameter( kEventParamKeyModifiers, &inKeyModifiers );
 +
 +			EventMouseButton inMouseButton;
 +			event.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton );
 +			if (inMouseButton == kEventMouseButtonTertiary) {
 +				if (inKeyModifiers & optionKey) {
 +					const char *test = "\001This is a test calltip This is a test calltip This is a test calltip";
 +					scintilla->WndProc( SCI_CALLTIPSHOW, 0, (long int)test );
 +				} else {
 +					char *list = "test_1?0 test_2 test_3 test_4 test_5 test_6 test_7 test_8 test_9 test_10 test_11 test_12";
 +					scintilla->WndProc( SCI_AUTOCSHOW, 0, (long int)list );
 +				}
 +				return noErr;
 +			}
 +		}
 +	
 +	return eventNotHandledErr;
 +}
 +
 +int main(int argc, char* argv[])
 +{
 +    IBNibRef 		nibRef;
 +    WindowRef 		window;
 +    
 +    OSStatus		err;
 +
 +    // Create a Nib reference passing the name of the nib file (without the .nib extension)
 +    // CreateNibReference only searches into the application bundle.
 +    err = CreateNibReference(CFSTR("main"), &nibRef);
 +    require_noerr( err, CantGetNibRef );
 +    
 +    // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
 +    // object. This name is set in InterfaceBuilder when the nib is created.
 +    err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
 +    require_noerr( err, CantSetMenuBar );
 +    
 +    // Then create a window. "MainWindow" is the name of the window object. This name is set in 
 +    // InterfaceBuilder when the nib is created.
 +    err = CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window);
 +    require_noerr( err, CantCreateWindow );
 +
 +    // We don't need the nib reference anymore.
 +    DisposeNibReference(nibRef);
 +    
 +
 +    HIRect boundsRect;
 +    // GOOD and BAD methods off embedding into a window.  This is used
 +    // to test Window::SetPositionRelative under different situations.
 +#define GOOD
 +#ifdef GOOD
 +#ifdef USE_CONTROL
 +    ControlRef root;
 +    GetRootControl(window, &root);
 +#else
 +    HIViewRef root;
 +    HIViewFindByID(HIViewGetRoot(window),
 +    		   kHIViewWindowContentID,
 +    		   &root);
 +#endif
 +    HIViewGetBounds(root, &boundsRect);
 +
 +#else // BAD like mozilla
 +    HIViewRef root;
 +    root = HIViewGetRoot(window);
 +
 +    Rect cBounds, sBounds;
 +    GetWindowBounds(window, kWindowContentRgn, &cBounds);
 +    GetWindowBounds(window, kWindowStructureRgn, &sBounds);
 +    boundsRect.origin.x = cBounds.left - sBounds.left;
 +    boundsRect.origin.y = cBounds.top - sBounds.top;
 +    boundsRect.size.width = cBounds.right - cBounds.left;
 +    boundsRect.size.height = cBounds.bottom - cBounds.top;
 +#endif
 +
 +    // get a scintilla control, and add it to it's parent container
 +    HIViewRef sciView;
 +    sciView = scintilla_new();
 +    HIViewAddSubview(root, sciView);
 +
 +	// some scintilla init
 +	ScintillaMacOSX* scintilla;
 +	GetControlProperty( sciView, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
 +
 +	scintilla->WndProc( SCI_SETLEXER, SCLEX_CPP, 0);
 +	scintilla->WndProc( SCI_SETSTYLEBITS, 5, 0);
 +	/*
 +	these fail compilation on osx now
 +	scintilla->WndProc( SCI_SETPROPERTY, "fold", (long int)"1");
 +	scintilla->WndProc( SCI_SETPROPERTY, "fold.compact", (long int)"0");
 +	scintilla->WndProc( SCI_SETPROPERTY, "fold.comment", (long int)"1");
 +	scintilla->WndProc( SCI_SETPROPERTY, "fold.preprocessor", (long int)"1");
 +	*/
 +	
 +	scintilla->WndProc( SCI_REGISTERIMAGE, 0, (long int)ac_class);
 +
 +	scintilla->WndProc( SCI_SETMARGINTYPEN, 0, (long int)SC_MARGIN_NUMBER);
 +	scintilla->WndProc( SCI_SETMARGINWIDTHN, 0, (long int)30);
 +	scintilla->WndProc( SCI_SETMARGINTYPEN, 1, (long int)SC_MARGIN_SYMBOL);
 +	scintilla->WndProc( SCI_SETMARGINMASKN, 1, (long int)SC_MASK_FOLDERS);
 +	scintilla->WndProc( SCI_SETMARGINWIDTHN, 1, (long int)20);
 +	scintilla->WndProc( SCI_SETMARGINTYPEN, 2, (long int)SC_MARGIN_SYMBOL);
 +	scintilla->WndProc( SCI_SETMARGINWIDTHN, 2, (long int)16);
 +	//scintilla->WndProc( SCI_SETWRAPMODE, SC_WRAP_WORD, 0);
 +	//scintilla->WndProc( SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_END | SC_WRAPVISUALFLAG_START, 0);
 +	
 +    // set the size of scintilla to the size of the container
 +    HIViewSetFrame( sciView, &boundsRect );
 +
 +    // bind the size of scintilla to the size of it's container window
 +    HIViewSetLayoutInfo(sciView, &kBindToParentLayout);
 +    
 +    // setup some event handling
 +    static const EventTypeSpec kWindowMouseEvents[] =
 +      {
 +	{ kEventClassMouse, kEventMouseDown },
 +      };
 +
 +    InstallEventHandler( GetWindowEventTarget( window ), WindowEventHandler,
 +			 GetEventTypeCount( kWindowMouseEvents ), kWindowMouseEvents, &sciView, NULL );
 +    
 +    // show scintilla
 +    ShowControl(sciView);
 +	
 +    SetAutomaticControlDragTrackingEnabledForWindow(window, true);
 +	
 +    // The window was created hidden so show it.
 +    ShowWindow( window );
 +    
 +    // Call the event loop
 +    RunApplicationEventLoop();
 +
 +CantCreateWindow:
 +CantSetMenuBar:
 +CantGetNibRef:
 +	return err;
 +}
 +
 diff --git a/macosx/SciTest/version.plist b/macosx/SciTest/version.plist new file mode 100644 index 000000000..df8c3dc7d --- /dev/null +++ b/macosx/SciTest/version.plist @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> +	<key>BuildVersion</key> +	<string>92</string> +	<key>CFBundleVersion</key> +	<string>1.0</string> +	<key>ProductBuildVersion</key> +	<string>7K571</string> +	<key>ProjectName</key> +	<string>NibPBTemplates</string> +	<key>SourceVersion</key> +	<string>1200000</string> +</dict> +</plist> diff --git a/macosx/ScintillaCallTip.cxx b/macosx/ScintillaCallTip.cxx new file mode 100644 index 000000000..6799b435a --- /dev/null +++ b/macosx/ScintillaCallTip.cxx @@ -0,0 +1,117 @@ + +#include "ScintillaMacOSX.h" +#include "ScintillaCallTip.h" +#include "CallTip.h" + +using namespace Scintilla; + +const CFStringRef ScintillaCallTip::kScintillaCallTipClassID = CFSTR( "org.scintilla.calltip" ); +const ControlKind ScintillaCallTip::kScintillaCallTipKind = { 'ejon', 'Scct' }; + +ScintillaCallTip::ScintillaCallTip( void* windowid ) : +        TView( reinterpret_cast<HIViewRef>( windowid ) ) +{ +    ActivateInterface( kMouse ); +    //  debugPrint = true; +} + +void ScintillaCallTip::Draw( +    RgnHandle           /*inLimitRgn*/, +    CGContextRef        inContext ) +{ +    // Get a reference to the Scintilla C++ object +    CallTip* ctip = NULL; +    OSStatus err; +    err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip ); +    assert(err == noErr); +    if (ctip == NULL) return; +     +    Rect contentBounds; +    GetControlBounds(GetViewRef(), &contentBounds); +     +    HIRect controlFrame; +    HIViewGetFrame( GetViewRef(), &controlFrame ); +     +    // what is the global pos? +    Surface *surfaceWindow = Surface::Allocate(); +    if (surfaceWindow) { +        surfaceWindow->Init(inContext, GetViewRef()); +        ctip->PaintCT(surfaceWindow); +        surfaceWindow->Release(); +        delete surfaceWindow; +    } + +} + +ControlPartCode ScintillaCallTip::HitTest( const HIPoint& where ) +{ +    if ( CGRectContainsPoint( Bounds(), where ) ) +        return 1; +    else +        return kControlNoPart; +} + +OSStatus ScintillaCallTip::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ ) +{ +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +    CallTip* ctip = NULL; +    ScintillaMacOSX *sciThis = NULL; +    OSStatus err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip ); +    err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis ); +    ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) )); +    sciThis->CallTipClick(); +    return noErr; +} + +OSStatus ScintillaCallTip::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ ) +{ +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +    return noErr; +} + +OSStatus ScintillaCallTip::MouseDragged( HIPoint& location, UInt32 /*modifiers*/, EventMouseButton /*button*/, UInt32 /*clickCount*/ ) +{ +    SetThemeCursor( kThemeArrowCursor ); +    return noErr; +} + +HIViewRef ScintillaCallTip::Create() +{ +    // Register the HIView, if needed +    static bool registered = false; + +    if ( not registered ) +    { +        TView::RegisterSubclass( kScintillaCallTipClassID, Construct ); +        registered = true; +    } + +    OSStatus err = noErr; +    EventRef event = CreateInitializationEvent(); +    assert( event != NULL ); + +    HIViewRef control = NULL; +    err = HIObjectCreate( kScintillaCallTipClassID, event, reinterpret_cast<HIObjectRef*>( &control ) ); +    ReleaseEvent( event ); +    if ( err == noErr ) { +        Platform::DebugPrintf("ScintillaCallTip::Create control %08X\n",control); +        return control; +    } +    return NULL;     +} + +OSStatus ScintillaCallTip::Construct( HIViewRef inControl, TView** outView ) +{ +    *outView = new ScintillaCallTip( inControl ); +    Platform::DebugPrintf("ScintillaCallTip::Construct scintilla %08X\n",*outView); +    if ( *outView != NULL ) +        return noErr; +    else +        return memFullErr; +} + +extern "C" { +HIViewRef scintilla_calltip_new() { +    return ScintillaCallTip::Create(); +} +} diff --git a/macosx/ScintillaCallTip.h b/macosx/ScintillaCallTip.h new file mode 100644 index 000000000..525804942 --- /dev/null +++ b/macosx/ScintillaCallTip.h @@ -0,0 +1,64 @@ +/* + *  ScintillaMacOSX.h + *  tutorial + * + *  Created by Evan Jones on Sun Sep 01 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ +#ifndef SCINTILLA_CALLTIP_H +#define SCINTILLA_CALLTIP_H + +#include "TView.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <time.h> + +#include "Platform.h" +#include "Scintilla.h" + +static const OSType scintillaCallTipType = 'Scct'; + +namespace Scintilla { + +class ScintillaCallTip : public TView +{ +public: +    // Private so ScintillaCallTip objects can not be copied +    ScintillaCallTip(const ScintillaCallTip &) : TView( NULL ) {} +    ScintillaCallTip &operator=(const ScintillaCallTip &) { return * this; } +    ~ScintillaCallTip() {}; + +public: +    /** This is the class ID that we've assigned to Scintilla. */ +    static const CFStringRef kScintillaCallTipClassID; +    static const ControlKind kScintillaCallTipKind; + +    ScintillaCallTip( void* windowid ); + +    /** Returns the HIView object kind, needed to subclass TView. */ +    virtual ControlKind GetKind() { return kScintillaCallTipKind; } + +private: + +    virtual ControlPartCode HitTest( const HIPoint& where ); +    virtual void Draw( RgnHandle rgn, CGContextRef gc ); +    virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); + +public: +    static HIViewRef Create(); +private: +    static OSStatus Construct( HIViewRef inControl, TView** outView ); +     +}; + + +} + + +#endif diff --git a/macosx/ScintillaListBox.cxx b/macosx/ScintillaListBox.cxx new file mode 100644 index 000000000..90c72d857 --- /dev/null +++ b/macosx/ScintillaListBox.cxx @@ -0,0 +1,103 @@ + +#include "ScintillaMacOSX.h" +#include "ScintillaListBox.h" + +using namespace Scintilla; + +const CFStringRef ScintillaListBox::kScintillaListBoxClassID = CFSTR( "org.scintilla.listbox" ); +const ControlKind ScintillaListBox::kScintillaListBoxKind = { 'ejon', 'Sclb' }; + +ScintillaListBox::ScintillaListBox( void* windowid ) : +		TView( reinterpret_cast<HIViewRef>( windowid ) ) +{ +  ActivateInterface( kMouse ); +  //  debugPrint = true; +} + +void ScintillaListBox::Draw( +	RgnHandle			/*inLimitRgn*/, +	CGContextRef		inContext ) +{ +	Rect contentBounds; +	GetControlBounds(GetViewRef(), &contentBounds); + +        HIRect controlFrame; +        HIViewGetFrame( GetViewRef(), &controlFrame ); + +	// what is the global pos? +	Surface *surfaceWindow = Surface::Allocate(); +	if (surfaceWindow) { +		surfaceWindow->Init(inContext, GetViewRef()); +		ctip->PaintCT(surfaceWindow); +		surfaceWindow->Release(); +		delete surfaceWindow; +	} + +} + +ControlPartCode ScintillaListBox::HitTest( const HIPoint& where ) +{ +	if ( CGRectContainsPoint( Bounds(), where ) ) +		return 1; +	else +		return kControlNoPart; +} + +OSStatus ScintillaListBox::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ ) +{ +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +    ListBox* ctip = NULL; +    ScintillaMacOSX *sciThis = NULL; +    OSStatus err = GetControlProperty( GetViewRef(), scintillaListBoxType, 0, sizeof( ctip ), NULL, &ctip ); +    err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis ); +    ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) )); +    sciThis->ListBoxClick(); +    return noErr; +} + +OSStatus ScintillaListBox::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ ) +{ +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +    return noErr; +} + +HIViewRef ScintillaListBox::Create() +{ +	// Register the HIView, if needed +	static bool registered = false; + +	if ( not registered ) +		{ +		TView::RegisterSubclass( kScintillaListBoxClassID, Construct ); +		registered = true; +		} + +	OSStatus err = noErr; +	EventRef event = CreateInitializationEvent(); +	assert( event != NULL ); + +	HIViewRef control = NULL; +	err = HIObjectCreate( kScintillaListBoxClassID, event, reinterpret_cast<HIObjectRef*>( &control ) ); +	ReleaseEvent( event ); +	if ( err == noErr ) { +	  Platform::DebugPrintf("ScintillaListBox::Create control %08X\n",control); +	  return control; +	} +	return NULL;	 +} + +OSStatus ScintillaListBox::Construct( HIViewRef inControl, TView** outView ) +{ +	*outView = new ScintillaListBox( inControl ); +	Platform::DebugPrintf("ScintillaListBox::Construct scintilla %08X\n",*outView); +	if ( *outView != NULL ) +		return noErr; +	else +		return memFullErr; +} + +extern "C" { +HIViewRef scintilla_listbox_new() { +	return ScintillaListBox::Create(); +} +} diff --git a/macosx/ScintillaListBox.h b/macosx/ScintillaListBox.h new file mode 100644 index 000000000..e26d354eb --- /dev/null +++ b/macosx/ScintillaListBox.h @@ -0,0 +1,63 @@ +/* + *  ScintillaMacOSX.h + *  tutorial + * + *  Created by Evan Jones on Sun Sep 01 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ +#ifndef SCINTILLA_LISTBOX_H +#define SCINTILLA_LISTBOX_H + +#include "TView.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <time.h> + +#include "Platform.h" +#include "Scintilla.h" + +static const OSType scintillaListBoxType = 'sclb'; + +namespace Scintilla { + +class ScintillaListBox : public TView +{ +public: +        // Private so ScintillaListBox objects can not be copied +        ScintillaListBox(const ScintillaListBox &) : TView( NULL ) {} +        ScintillaListBox &operator=(const ScintillaListBox &) { return * this; } +	~ScintillaListBox() {}; + +public: +	/** This is the class ID that we've assigned to Scintilla. */ +	static const CFStringRef kScintillaListBoxClassID; +	static const ControlKind kScintillaListBoxKind; + +	ScintillaListBox( void* windowid ); + +	/** Returns the HIView object kind, needed to subclass TView. */ +	virtual ControlKind GetKind() { return kScintillaListBoxKind; } + +private: + +	virtual ControlPartCode HitTest( const HIPoint& where ); +	virtual void Draw( RgnHandle rgn, CGContextRef gc ); +	virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +	virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); + +public: +	static HIViewRef Create(); +private: +	static OSStatus Construct( HIViewRef inControl, TView** outView ); +	 +}; + + +} + + +#endif diff --git a/macosx/ScintillaMacOSX.cxx b/macosx/ScintillaMacOSX.cxx new file mode 100644 index 000000000..9ac746f4b --- /dev/null +++ b/macosx/ScintillaMacOSX.cxx @@ -0,0 +1,2118 @@ +// Scintilla source code edit control +// ScintillaMacOSX.cxx - Mac OS X subclass of ScintillaBase +// Copyright 2003 by Evan Jones <ejones@uwaterloo.ca> +// Based on ScintillaGTK.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 "ScintillaMacOSX.h" +#include "UniConversion.h" + +using namespace Scintilla; + +const CFStringRef ScintillaMacOSX::kScintillaClassID = CFSTR( "org.scintilla.scintilla" ); +const ControlKind ScintillaMacOSX::kScintillaKind = { 'ejon', 'Scin' }; + +extern "C" HIViewRef scintilla_calltip_new(void); + +#ifndef WM_UNICHAR +#define WM_UNICHAR                      0x0109 +#endif + +// required for paste/dragdrop, see comment in paste function below +static int BOMlen(unsigned char *cstr) { +  switch(cstr[0]) {  +  case 0xEF: // BOM_UTF8 +    if (cstr[1] == 0xBB && cstr[2] == 0xBF) { +      return 3; +    } +    break; +  case 0xFE: +    if (cstr[1] == 0xFF) { +      if (cstr[2] == 0x00 && cstr[3] == 0x00) { +        return 4; +      } +      return 2; +    } +    break; +  case 0xFF: +    if (cstr[1] == 0xFE) { +      if (cstr[2] == 0x00 && cstr[3] == 0x00) { +        return 4; +      } +      return 2; +    } +    break; +  case 0x00: +    if (cstr[1] == 0x00) { +      if (cstr[2] == 0xFE && cstr[3] == 0xFF) { +        return 4; +      } +      if (cstr[2] == 0xFF && cstr[3] == 0xFE) { +        return 4; +      } +      return 2; +    } +    break; +  } + +  return 0; +} + +ScintillaMacOSX::ScintillaMacOSX( void* windowid ) : +        TView( reinterpret_cast<HIViewRef>( windowid ) ) +{ +    wMain = windowid; +    OSStatus err; +    err = GetThemeMetric( kThemeMetricScrollBarWidth, &scrollBarFixedSize ); +    assert( err == noErr ); + +    mouseTrackingRef = NULL; +    mouseTrackingID.signature = scintillaMacOSType; +    mouseTrackingID.id = (SInt32)this; +    capturedMouse = false; + +    // Enable keyboard events and mouse events +#if !defined(CONTAINER_HANDLES_EVENTS) +    ActivateInterface( kKeyboardFocus ); +    ActivateInterface( kMouse ); +    ActivateInterface( kDragAndDrop ); +#endif +    ActivateInterface( kMouseTracking ); + +    Initialise(); + +    // Create some bounds rectangle which will just get reset to the correct rectangle later +    Rect tempScrollRect; +    tempScrollRect.top = -1; +    tempScrollRect.left = 400; +    tempScrollRect.bottom = 300; +    tempScrollRect.right = 450; + +    // Create the scroll bar with fake values that will get set correctly later +    err = CreateScrollBarControl( this->GetOwner(), &tempScrollRect, 0, 0, 100, 100, true, LiveScrollHandler, &vScrollBar ); +    assert( vScrollBar != NULL && err == noErr ); +    err = CreateScrollBarControl( this->GetOwner(), &tempScrollRect, 0, 0, 100, 100, true, LiveScrollHandler, &hScrollBar ); +    assert( hScrollBar != NULL && err == noErr ); + +    // Set a property on the scrollbars to store a pointer to the Scintilla object +    ScintillaMacOSX* objectPtr = this; +    err = SetControlProperty( vScrollBar, scintillaMacOSType, 0, sizeof( this ), &objectPtr ); +    assert( err == noErr ); +    err = SetControlProperty( hScrollBar, scintillaMacOSType, 0, sizeof( this ), &objectPtr ); +    assert( err == noErr ); + +    // set this into our parent control so we can be retrieved easily at a later time  +    // (see scintilla_send below) +    err = SetControlProperty( reinterpret_cast<HIViewRef>( windowid ), scintillaMacOSType, 0, sizeof( this ), &objectPtr ); +    assert( err == noErr ); + +    // Tell Scintilla not to buffer: Quartz buffers drawing for us +    // TODO: Can we disable this option on Mac OS X? +    WndProc( SCI_SETBUFFEREDDRAW, 0, 0 ); +    // Turn on UniCode mode +    WndProc( SCI_SETCODEPAGE, SC_CP_UTF8, 0 ); + +    const EventTypeSpec commandEventInfo[] = { +        { kEventClassCommand, kEventProcessCommand }, +        { kEventClassCommand, kEventCommandUpdateStatus }, +    }; + +    err = InstallEventHandler( GetControlEventTarget( reinterpret_cast<HIViewRef>( windowid ) ),  +                   CommandEventHandler, +                   GetEventTypeCount( commandEventInfo ),  +                   commandEventInfo, +                   this, NULL); +    assert( err == noErr ); +} + +ScintillaMacOSX::~ScintillaMacOSX() { +    // If the window is closed and the timer is not removed, +    // A segment violation will occur when it attempts to fire the timer next. +    if ( mouseTrackingRef != NULL ) { +        ReleaseMouseTrackingRegion(mouseTrackingRef); +    } +    mouseTrackingRef = NULL; +    SetTicking(false); +} + +void ScintillaMacOSX::Initialise() { +    // TODO: Do anything here? Maybe this stuff should be here instead of the constructor? +} + +void ScintillaMacOSX::Finalise() { +    SetTicking(false); +    ScintillaBase::Finalise(); +} + +// -------------------------------------------------------------------------------------------------------------- +// +// IsDropInFinderTrash - Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash. +// +#pragma segment Drag + +Boolean IsDropInFinderTrash(AEDesc *dropLocation) +{ +    OSErr      result; +    AEDesc      dropSpec; +    FSSpec      *theSpec; +    CInfoPBRec    thePB; +    short      trashVRefNum; +    long      trashDirID; +   +    //  Coerce the dropLocation descriptor into an FSSpec. If there's no dropLocation or +    //  it can't be coerced into an FSSpec, then it couldn't have been the Trash. + +  if ((dropLocation->descriptorType != typeNull) && +    (AECoerceDesc(dropLocation, typeFSS, &dropSpec) == noErr))  +    { +        unsigned char flags = HGetState((Handle)dropSpec.dataHandle); +         +        HLock((Handle)dropSpec.dataHandle); +        theSpec = (FSSpec *) *dropSpec.dataHandle; +         +        //  Get the directory ID of the given dropLocation object. +         +        thePB.dirInfo.ioCompletion = 0L; +        thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name; +        thePB.dirInfo.ioVRefNum = theSpec->vRefNum; +        thePB.dirInfo.ioFDirIndex = 0; +        thePB.dirInfo.ioDrDirID = theSpec->parID; +         +        result = PBGetCatInfoSync(&thePB); +         +        HSetState((Handle)dropSpec.dataHandle, flags); +        AEDisposeDesc(&dropSpec); +         +        if (result != noErr) +            return false; +         +        //  If the result is not a directory, it must not be the Trash. +         +        if (!(thePB.dirInfo.ioFlAttrib & (1 << 4))) +            return false; +         +        //  Get information about the Trash folder. +         +        FindFolder(theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID); +         +        //  If the directory ID of the dropLocation object is the same as the directory ID +        //  returned by FindFolder, then the drop must have occurred into the Trash. +         +        if (thePB.dirInfo.ioDrDirID == trashDirID) +            return true; +    } + +    return false; + +} // IsDropInFinderTrash + +HIPoint ScintillaMacOSX::GetLocalPoint(::Point pt) +{ +    // get the mouse position so we can offset it +    Rect bounds; +    GetWindowBounds( GetOwner(), kWindowStructureRgn, &bounds ); + +    PRectangle hbounds = wMain.GetPosition(); +    HIViewRef parent = HIViewGetSuperview(GetViewRef()); +    Rect pbounds; +    GetControlBounds(parent, &pbounds); +       +    bounds.left += pbounds.left + hbounds.left; +    bounds.top += pbounds.top + hbounds.top; + +    HIPoint offset = { pt.h - bounds.left, pt.v - bounds.top }; +    return offset; +} + +void ScintillaMacOSX::StartDrag() { +#define DRAG_DROP_PASTEBOARD +    if (currentPos == anchor) return; + +    SelectionText selectedText; +    CopySelectionRange(&selectedText); + +    // some of this taken from copytoclipboard +    if (selectedText.len == 0) +        return; + +    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); + +    // Create a CFString from the ASCII/UTF8 data, convert it to UTF16 +    CFStringRef string = CFStringCreateWithBytes( NULL, reinterpret_cast<UInt8*>( selectedText.s ), selectedText.len - 1, encoding, false ); +    assert( string != NULL ); + +#ifndef DRAG_DROP_PASTEBOARD +    CFIndex numUniChars = CFStringGetLength( string ); +    UniChar* buffer = new UniChar[ numUniChars ]; +    CFStringGetCharacters( string, CFRangeMake( 0, numUniChars ), buffer ); + +    // Create an c string byte buffer +    CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; +    char* cstring = new char[maximumByteLength]; +    CFIndex usedBufferLength = 0; +    CFIndex numCharsConverted; +    numCharsConverted = CFStringGetBytes( string, CFRangeMake( 0, numUniChars ), encoding, +                              '?', false, reinterpret_cast<UInt8*>( cstring ), +                              maximumByteLength, &usedBufferLength ); +    cstring[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string +    assert( numCharsConverted == numUniChars ); +#endif +     +    // calculate the bounds of the selection +        PRectangle client = GetTextRectangle(); +    int selStart = Platform::Minimum(anchor, currentPos); +    int selEnd = Platform::Maximum(anchor, currentPos); +    int startLine = pdoc->LineFromPosition(selStart); +    int endLine = pdoc->LineFromPosition(selEnd); +    Point pt; +    int startPos, endPos, ep; +    Rect rcSel; +    rcSel.top = rcSel.bottom = rcSel.right = rcSel.left = -1; +    for (int l = startLine; l <= endLine; l++) { +        startPos = WndProc(SCI_GETLINESELSTARTPOSITION, l, 0); +        endPos = WndProc(SCI_GETLINESELENDPOSITION, l, 0); +        if (endPos == startPos) continue; +        // step back a position if we're counting the newline +        ep = WndProc(SCI_GETLINEENDPOSITION, l, 0); +        if (endPos > ep) endPos = ep; +   +        pt = LocationFromPosition(startPos); // top left of line selection +        if (pt.x < rcSel.left || rcSel.left < 0) rcSel.left = pt.x; +        if (pt.y < rcSel.top || rcSel.top < 0) rcSel.top = pt.y; +   +        pt = LocationFromPosition(endPos); // top right of line selection +        pt.y += vs.lineHeight; // get to the bottom of the line +        if (pt.x > rcSel.right || rcSel.right < 0) { +            if (pt.x > client.right) +                rcSel.right = client.right; +            else +                rcSel.right = pt.x; +        } +        if (pt.y > rcSel.bottom || rcSel.bottom < 0) { +            if (pt.y > client.bottom) +                rcSel.bottom = client.bottom; +            else +                rcSel.bottom = pt.y; +        } +    } + +    // must convert to global coordinates for drag regions, but also save the +    // image rectangle for further calculations and copy operations +    PRectangle imageRect = PRectangle(rcSel.left, rcSel.top, rcSel.right, rcSel.bottom); +    QDLocalToGlobalRect(GetWindowPort(GetOwner()), &rcSel); + +    // get the mouse position so we can offset it +    HIPoint offset = GetLocalPoint(mouseDownEvent.where); +    offset.y = (imageRect.top * 1.0) - offset.y; +    offset.x = (imageRect.left * 1.0) - offset.x; + +    // to get a bitmap of the text we're dragging, we just use Paint on a  +    // pixmap surface. +    SurfaceImpl *sw = new SurfaceImpl(); +    SurfaceImpl *pixmap = NULL; + +    if (sw) { +        pixmap = new SurfaceImpl(); +        if (pixmap) { +            client = GetClientRectangle(); +            paintState = painting; +            sw->InitPixMap( client.Width(), client.Height(), NULL, NULL ); +             +            Paint(sw, imageRect); +            paintState = notPainting; +     +            pixmap->InitPixMap( imageRect.Width(), imageRect.Height(), NULL, NULL ); +     +            CGContextRef gc = pixmap->GetContext();  +     +            // to make Paint() work on a bitmap, we have to flip our coordinates +            // and translate the origin +            //fprintf(stderr, "translate to %d\n", client.Height() ); +            CGContextTranslateCTM(gc, 0, imageRect.Height()); +            CGContextScaleCTM(gc, 1.0, -1.0); +     +            pixmap->CopyImageRectangle( *sw, imageRect, PRectangle( 0, 0, imageRect.Width(), imageRect.Height() )); +            // XXX TODO: overwrite any part of the image that is not part of the +            //           selection to make it transparent.  right now we just use +            //           the full rectangle which may include non-selected text. +        } +        sw->Release(); +        delete sw; +    } + +    // now we initiate the drag session + +    RgnHandle dragRegion = NewRgn(); +    RgnHandle tempRegion; +    DragRef inDrag; +    DragAttributes attributes; +    AEDesc dropLocation; +    SInt16 mouseDownModifiers, mouseUpModifiers; +    bool copyText; +    CGImageRef image = NULL; + +    RectRgn(dragRegion, &rcSel); + +#ifdef DRAG_DROP_PASTEBOARD +    PasteboardRef theClipboard; +    PasteboardCreate( kPasteboardClipboard, &theClipboard ); +    PasteboardClear( theClipboard ); + +    CFDataRef data = NULL; +    data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingMacRoman, 0 ); +    PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1,  +                            CFSTR("com.apple.traditional-mac-plain-text"), +                            data, 0 ); +    CFRelease(data); +    data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingUnicode, 0 ); +    PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1,  +                            CFSTR("public.utf16-plain-text"), +                            data, 0 ); +    CFRelease(data); +    NewDragWithPasteboard( theClipboard, &inDrag); +#else +    NewDrag(&inDrag); +    AddDragItemFlavor(inDrag, 1, 'utxt', buffer, sizeof( UniChar ) * numUniChars, 0); +    AddDragItemFlavor(inDrag, 1, 'txt', cstring, sizeof( char ) * usedBufferLength, 0); +#endif + +    //  Set the item's bounding rectangle in global coordinates. +    SetDragItemBounds(inDrag, 1, &rcSel); + +    //  Prepare the drag region. +    tempRegion = NewRgn(); +    CopyRgn(dragRegion, tempRegion); +    InsetRgn(tempRegion, 1, 1); +    DiffRgn(dragRegion, tempRegion, dragRegion); +    DisposeRgn(tempRegion); + +    // if we have a pixmap, lets use that +    if (pixmap) { +        image = pixmap->GetImage(); +        SetDragImageWithCGImage (inDrag, image, &offset, kDragStandardTranslucency); +    } + +    //  Drag the text. TrackDrag will return userCanceledErr if the drop whooshed back for any reason. +    inDragSession = true; +    OSErr error = TrackDrag(inDrag, &mouseDownEvent, dragRegion); +    inDragSession = false; + +    //  Check to see if the drop occurred in the Finder's Trash. If the drop occurred +    //  in the Finder's Trash and a copy operation wasn't specified, delete the +    //  source selection. Note that we can continute to get the attributes, drop location +    //  modifiers, etc. of the drag until we dispose of it using DisposeDrag. +    if (error == noErr) { +        GetDragAttributes(inDrag, &attributes); +        if (!(attributes & kDragInsideSenderApplication)) +        { +            GetDropLocation(inDrag, &dropLocation); +     +            GetDragModifiers(inDrag, 0L, &mouseDownModifiers, &mouseUpModifiers); +            copyText = (mouseDownModifiers | mouseUpModifiers) & optionKey; +     +            if ((!copyText) && (IsDropInFinderTrash(&dropLocation))) +            { +                // delete the selected text from the buffer +                ClearSelection(); +            } +     +            AEDisposeDesc(&dropLocation); +        } +    } + +    // Dispose of this drag, 'cause we're done. +    DisposeDrag(inDrag); +    DisposeRgn(dragRegion); +    CFRelease( string ); + +    if (pixmap) { +        CGImageRelease(image); +        pixmap->Release(); +        delete pixmap; +    } + +    // Done with the UniChar* buffer +#ifdef DRAG_DROP_PASTEBOARD +    CFRelease( theClipboard ); +#else +    delete[] buffer; +    buffer = NULL;   +    delete[] cstring; +    cstring = NULL; +#endif +} + +void ScintillaMacOSX::SetDragCursor(DragRef inDrag) +{ +    DragAttributes attributes; +    SInt16 modifiers = 0;  +    ThemeCursor cursor = kThemeCopyArrowCursor; +    GetDragAttributes( inDrag, &attributes ); + +    if ( attributes & kDragInsideSenderWindow ) { +        GetDragModifiers(inDrag, &modifiers, NULL, NULL); +        switch (modifiers & ~btnState)  // Filter out btnState (on for drop) +        { +        case optionKey: +            // it's a copy, leave it as a copy arrow +            break; +       +        case cmdKey: +        case cmdKey | optionKey: +        default: +            // what to do with these?  rectangular drag? +            cursor = kThemeArrowCursor; +            break; +        } +    } +    SetThemeCursor(cursor); +} + +bool ScintillaMacOSX::DragEnter(DragRef inDrag ) +{ +    if (!DragWithin(inDrag)) +        return false; + +    DragAttributes attributes; +    GetDragAttributes( inDrag, &attributes ); +     +    // only show the drag hilight if the drag has left the sender window per HI spec +    if( attributes & kDragHasLeftSenderWindow ) +    { +        HIRect    textFrame; +        RgnHandle  hiliteRgn = NewRgn(); +         +        // get the text view's frame ... +        HIViewGetFrame( GetViewRef(), &textFrame ); +         +        // ... and convert it into a region for ShowDragHilite +        HIShapeRef textShape = HIShapeCreateWithRect( &textFrame ); +        HIShapeGetAsQDRgn( textShape, hiliteRgn ); +        CFRelease( textShape ); +         +        // add the drag hilight to the inside of the text view +        ShowDragHilite( inDrag, hiliteRgn, true ); +         +        DisposeRgn( hiliteRgn ); +    } +    SetDragCursor(inDrag); +    return true; +} + +Scintilla::Point ScintillaMacOSX::GetDragPoint(DragRef inDrag) +{ +    ::Point mouse, globalMouse; +    GetDragMouse(inDrag, &mouse, &globalMouse); +    QDGlobalToLocalPoint(GetWindowPort(GetOwner()), &globalMouse); +    HIPoint hiPoint = {globalMouse.h, globalMouse.v}; +    return Point(static_cast<int>(hiPoint.x), static_cast<int>(hiPoint.y)); +} + + +void ScintillaMacOSX::DragScroll() +{ +#define RESET_SCROLL_TIMER(lines) \ +  scrollSpeed = (lines); \ +  scrollTicks = 2000; + +    if (posDrag == invalidPosition) { +        RESET_SCROLL_TIMER(1); +        return; +    } +    Point dragMouse = LocationFromPosition(posDrag); +    int line = pdoc->LineFromPosition(posDrag); +    int currentVisibleLine = cs.DisplayFromDoc(line); +    int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen() - 1, pdoc->LinesTotal() - 1); + +    if (currentVisibleLine <= topLine && topLine > 0) { +        ScrollTo( topLine - scrollSpeed ); +    } else if (currentVisibleLine >= lastVisibleLine) { +        ScrollTo( topLine + scrollSpeed ); +    } else { +        RESET_SCROLL_TIMER(1); +        return; +    } +    if (scrollSpeed == 1) { +        scrollTicks -= timer.tickSize; +        if (scrollTicks <= 0) { +            RESET_SCROLL_TIMER(5); +        } +    } + +    SetDragPosition(PositionFromLocation(dragMouse)); + +#undef RESET_SCROLL_TIMER +} + +bool ScintillaMacOSX::DragWithin(DragRef inDrag ) +{ +    PasteboardRef pasteBoard; +    OSStatus status = GetDragData(inDrag, pasteBoard, NULL); +    if (status != noErr) { +        return false; +    } + +    ::Point mouse, globalMouse; +    GetDragMouse(inDrag, &mouse, &globalMouse); +    QDGlobalToLocalPoint(GetWindowPort(GetOwner()), &globalMouse); +    HIPoint globalHit = {globalMouse.h, globalMouse.v}; +    // HIPoint localHit = {mouse.h, mouse.v}; + +    if (!CGRectContainsPoint( Bounds(), globalHit )) { +        return false; +    } + +    SetDragPosition(PositionFromLocation(Point(static_cast<int>(globalHit.x),static_cast<int>(globalHit.y)))); +    SetDragCursor(inDrag); + +    return true; +} + +bool ScintillaMacOSX::DragLeave(DragRef inDrag ) +{ +    HideDragHilite( inDrag ); +    SetDragPosition(invalidPosition); +    WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); +    return true; +} + +OSStatus ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, CFStringRef *textString) +{ +  // TODO: add support for special flavors: flavorTypeHFS and flavorTypePromiseHFS so we +  //       can handle files being dropped on the editor +    OSStatus status; +    status = GetDragPasteboard(inDrag, &pasteBoard); +    if (status != noErr) { +        return dragNotAcceptedErr; +    } + +    // how many items in the pasteboard? +    ItemCount i, itemCount; +    status = PasteboardGetItemCount(pasteBoard, &itemCount); +    if (status != noErr) { +        return dragNotAcceptedErr; +    } + +    // as long as we didn't get our text, let's loop on the items. We stop as soon as we get it +    CFArrayRef flavorTypeArray = NULL; +    bool haveMatch = false; +    for (i = 1; i <= itemCount; i++) +    { +        PasteboardItemID itemID; +        CFIndex j, flavorCount = 0; + +        status = PasteboardGetItemIdentifier(pasteBoard, i, &itemID); +        if (status != noErr) { +            return dragNotAcceptedErr; +        } + +        // how many flavors in this item? +        status = PasteboardCopyItemFlavors(pasteBoard, itemID, &flavorTypeArray); +        if (status != noErr) { +            return dragNotAcceptedErr; +        } + +        if (flavorTypeArray != NULL) +            flavorCount = CFArrayGetCount(flavorTypeArray); + +        // as long as we didn't get our text, let's loop on the flavors. We stop as soon as we get it +        for(j = 0; j < flavorCount; j++) +        { +            CFDataRef flavorData; +            CFStringRef flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, j); +            if (flavorType != NULL) { +                if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))) // this is 'utxt' +                { +                    // if we got a flavor match, and we have no textString, we just want +                    // to know that we can accept this drag data, so jump out now +                    if (textString == NULL) { +                        haveMatch = true; +                        goto DragDataRetrieved; +                    } +                    if (PasteboardCopyItemFlavorData(pasteBoard, itemID, flavorType, &flavorData) == noErr) +                    { +                        CFIndex flavorDataSize = CFDataGetLength(flavorData); +                     +                        // getting the text +                        *textString = CFStringCreateWithCharacters(NULL,  +                                  (UniChar *)CFDataGetBytePtr(flavorData),  +                                  flavorDataSize >> 1); +                        CFRelease(flavorData); +                        goto DragDataRetrieved; +                    } +                } +            } +        } +    } +DragDataRetrieved: +    if (flavorTypeArray != NULL) CFRelease(flavorTypeArray); +    if (haveMatch || textString != NULL && *textString != NULL)  +        return noErr; +    return dragNotAcceptedErr; +} + +OSStatus ScintillaMacOSX::DragReceive(DragRef inDrag ) +{ +    OSStatus status; +    PasteboardRef pasteBoard; +    CFStringRef textString = NULL; +    status = GetDragData(inDrag, pasteBoard, &textString); +    if (status != noErr) { +        return dragNotAcceptedErr; +    } + +    // getting the length of the text and setting the value +    if (textString == NULL) { +        return noErr; +    } + +    // XXX the following is identical (ALMOST) to code in Paste + +    // Allocate a buffer, plus the null byte +    CFIndex numUniChars = CFStringGetLength( textString ); +    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); +    CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; +    char* cstring = new char[maximumByteLength]; +    CFIndex usedBufferLength = 0; +    CFIndex numCharsConverted; +    numCharsConverted = CFStringGetBytes( textString, CFRangeMake( 0, numUniChars ), encoding, +                              '?', false, reinterpret_cast<UInt8*>( cstring ), +                              maximumByteLength, &usedBufferLength ); +    cstring[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string +    assert( numCharsConverted == numUniChars ); + +    // Default allocator releases both the CFString and the UniChar buffer (text) +    CFRelease( textString ); +    textString = NULL;       + +    // determine whether a BOM is in the string.  Apps like Emacs prepends a BOM +    // to the string, CFStrinGetBytes reflects that (though it may change in the conversion) +    // so we need to remove it before pasting into our buffer.  TextWrangler has no +    // problem dealing with BOM when pasting into it. +    int bomLen = BOMlen((unsigned char *)cstring); +     +    // convert line endings to the document line ending +    int droppedLen = 0; +    char *droppedText = Document::TransformLineEnds(&droppedLen, +                                                cstring + bomLen, +                                                usedBufferLength - bomLen, +                                                pdoc->eolMode); +     +    pdoc->BeginUndoAction(); + +    // figure out if this is a move or a paste +    DragAttributes attributes; +    SInt16 modifiers = 0;  +    GetDragAttributes( inDrag, &attributes ); + +    int position = PositionFromLocation(GetDragPoint(inDrag)); +    int selStart = Platform::Minimum(anchor, currentPos); +    int selEnd = Platform::Maximum(anchor, currentPos); +    if ( attributes & kDragInsideSenderWindow ) { +        if (position >= selStart && position <= selEnd) { +            // droping on top of what we dragged, we should ignore this +            goto endDrag; +        } +        GetDragModifiers(inDrag, NULL, NULL, &modifiers); +        switch (modifiers & ~btnState)  // Filter out btnState (on for drop) +        { +        case optionKey: +            // default is copy text +            break; +       +        case cmdKey: +        case cmdKey | optionKey: +        default: +            // what to do with these?  rectangular drag? +            position = selStart; +            ClearSelection(); +            break; +        } +    } else { +        if (position >= selStart && position <= selEnd) { +            // droping on top of a selection from another app or control, clear it +            position = selStart; +            ClearSelection(); +        } +    } + +    // lets put the text in our document now +    if ( pdoc->InsertString( position, droppedText, droppedLen ) ) +    { +        SetEmptySelection( currentPos + droppedLen ); +    } + +endDrag: +    delete[] droppedText; +    delete[] cstring; +    cstring = NULL; +     +    pdoc->EndUndoAction(); +    NotifyChange(); +     +    // dragleave IS called, but for some reason (probably to do with inDrag) +    // the hide hilite does not happen unless we do it here +    HideDragHilite( inDrag ); + +    return noErr; +} + +/** The simulated message loop. */ +sptr_t ScintillaMacOSX::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { +    switch (iMessage) { +    case SCI_GETDIRECTFUNCTION: +        Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Returning DirectFunction address.\n" ); +        return reinterpret_cast<sptr_t>( DirectFunction ); +     +    case SCI_GETDIRECTPOINTER: +        Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Returning Direct pointer address.\n" ); +        return reinterpret_cast<sptr_t>( this ); +     +    case SCI_GRABFOCUS: +        Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Got an unhandled message. Ignoring it.\n" ); +         break; +    case WM_UNICHAR: +        if (IsUnicodeMode()) { +            char utfval[4]; +            wchar_t wcs[2] = {wParam, 0}; +            unsigned int len = UTF8Length(wcs, 1); +            UTF8FromUTF16(wcs, 1, utfval, len); +            AddCharUTF(utfval, len); +            return 1; +        } else { +            return 0; +        } + +    default: +        unsigned int r = ScintillaBase::WndProc(iMessage, wParam, lParam); + +        return r; +    } +    return 0l; +} + +sptr_t ScintillaMacOSX::DefWndProc(unsigned int, uptr_t, sptr_t) { +    return 0; +} + +void ScintillaMacOSX::SetTicking(bool on) { +    if (timer.ticking != on) { +        timer.ticking = on; +        if (timer.ticking) { +            // Scintilla ticks = milliseconds +            EventLoopTimerRef timerRef = NULL; +            InstallTimer( timer.tickSize * kEventDurationMillisecond, &timerRef ); +            assert( timerRef != NULL ); +            timer.tickerID = reinterpret_cast<TickerID>( timerRef ); +        } else if ( timer.tickerID != NULL ) { +            RemoveEventLoopTimer( reinterpret_cast<EventLoopTimerRef>( timer.tickerID ) ); +        } +    } +    timer.ticksToWait = caret.period; +} + +bool ScintillaMacOSX::SetIdle(bool on) { +    if (on) { +        // Start idler, if it's not running. +        if (idler.state == false) { +            idler.state = true; +            EventLoopTimerRef idlTimer; +            InstallEventLoopIdleTimer(GetCurrentEventLoop(), +                                      timer.tickSize * kEventDurationMillisecond, +                                      75 * kEventDurationMillisecond, +                                      IdleTimerEventHandler, this, &idlTimer); +            idler.idlerID = reinterpret_cast<IdlerID>( idlTimer ); +        } +    } else { +        // Stop idler, if it's running +        if (idler.state == true) { +            idler.state = false; +            if (idler.idlerID != NULL) +                RemoveEventLoopTimer( reinterpret_cast<EventLoopTimerRef>( idler.idlerID ) ); +        } +    } +    return true; +} + +pascal void ScintillaMacOSX::IdleTimerEventHandler( EventLoopTimerRef inTimer,  +                                                    EventLoopIdleTimerMessage inState, +                                                    void *scintilla ) +{ +    ScintillaMacOSX *sciThis = reinterpret_cast<ScintillaMacOSX*>( scintilla ); +    bool ret = sciThis->Idle(); +    if (ret == false) { +        sciThis->SetIdle(false); +    } +} + +void ScintillaMacOSX::SetMouseCapture(bool on) { +    capturedMouse = on; +    if (mouseDownCaptures) { +        if (capturedMouse) { +            WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); +        } else { +            // reset to normal, buttonmove will change for other area's in the editor +            WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0); +        } +    } +} + +bool ScintillaMacOSX::HaveMouseCapture() { +    return capturedMouse; +} + +// The default GetClientRectangle calls GetClientPosition on wMain. +// We override it to return "view local" co-ordinates so we can draw properly +// plus we need to remove the space occupied by the scroll bars +PRectangle ScintillaMacOSX::GetClientRectangle() { +    PRectangle rc = wMain.GetClientPosition(); +    if (verticalScrollBarVisible) +        rc.right -= scrollBarFixedSize + 1; +    if (horizontalScrollBarVisible && (wrapState == eWrapNone)) +        rc.bottom -= scrollBarFixedSize + 1; +    // Move to origin +    rc.right -= rc.left; +    rc.bottom -= rc.top; +    rc.left = 0; +    rc.top = 0; +    return rc; +} + +// Synchronously paint a rectangle of the window. +void ScintillaMacOSX::SyncPaint(void* gc, PRectangle rc) { +    paintState = painting; +    rcPaint = rc; +    PRectangle rcText = GetTextRectangle(); +    paintingAllText = rcPaint.Contains(rcText); +    //Platform::DebugPrintf("ScintillaMacOSX::SyncPaint %0d,%0d %0d,%0d\n", +    //  rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom); +    Surface *sw = Surface::Allocate(); +    if (sw) { +        sw->Init( gc, wMain.GetID() ); +        Paint(sw, rc); +        if (paintState == paintAbandoned) { +          // XXX a bit of a hack to avoid excesive flashing when typing. +          paintState = painting; +          paintingAllText = true; +          Paint(sw, rc); +          // TODO: There is a chance that this causes an infinite drawing loop... +          wMain.InvalidateAll(); +        } +        sw->Release(); +        delete sw; +    } +    paintState = notPainting; +} + +void ScintillaMacOSX::ScrollText(int /*linesToMove*/) { +    // This function will invalidate the correct regions of the view, +    // So shortly after this happens, draw will be called. +    // But I'm not quite sure how this works ... +    // I have a feeling that it is only supposed to work in conjunction with an HIScrollView. +    // TODO: Cook up my own bitblt scroll: Grab the bits on screen, blit them shifted, invalidate the remaining stuff +    //CGRect r = CGRectMake( 0, 0, rc.Width(), rc.Height() ); +    //HIViewScrollRect( reinterpret_cast<HIViewRef>( wMain.GetID() ), NULL, 0, vs.lineHeight * linesToMove ); +    wMain.InvalidateAll(); +} + +void ScintillaMacOSX::SetVerticalScrollPos() { +    SetControl32BitValue( vScrollBar, topLine ); +} + +void ScintillaMacOSX::SetHorizontalScrollPos() { +    SetControl32BitValue( hScrollBar, xOffset ); +} + +bool ScintillaMacOSX::ModifyScrollBars(int nMax, int nPage) { +    Platform::DebugPrintf( "nMax: %d nPage: %d hScroll (%d -> %d) page: %d\n", nMax, nPage, 0, scrollWidth, GetTextRectangle().Width() ); +    // Minimum value = 0 +    // TODO: This is probably not needed, since we set this when the scroll bars are created +    SetControl32BitMinimum( vScrollBar, 0 ); +    SetControl32BitMinimum( hScrollBar, 0 ); + +    // Maximum vertical value = nMax + 1 - nPage (lines available to scroll) +    SetControl32BitMaximum( vScrollBar, Platform::Maximum( nMax + 1 - nPage, 0 ) ); +    // Maximum horizontal value = scrollWidth - GetTextRectangle().Width() (pixels available to scroll) +    SetControl32BitMaximum( hScrollBar, Platform::Maximum( scrollWidth - GetTextRectangle().Width(), 0 ) ); + +    // Vertical page size = nPage +    SetControlViewSize( vScrollBar, nPage ); +    // Horizontal page size = TextRectangle().Width() +    SetControlViewSize( hScrollBar, GetTextRectangle().Width() ); + +    // TODO: Verify what this return value is for +    // The scroll bar components will handle if they need to be rerendered or not +    return false; +} + +void ScintillaMacOSX::ReconfigureScrollBars() { +    PRectangle rc = wMain.GetClientPosition(); +    Resize(rc.Width(), rc.Height()); +} + +void ScintillaMacOSX::Resize(int width, int height) { +    // Get the horizontal/vertical size of the scroll bars +    GetThemeMetric( kThemeMetricScrollBarWidth, &scrollBarFixedSize ); + +    bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone); +    HIRect scrollRect; +    if (verticalScrollBarVisible) { +        scrollRect.origin.x = width - scrollBarFixedSize; +        scrollRect.origin.y = 0; +        scrollRect.size.width = scrollBarFixedSize; +        if (showSBHorizontal) { +            scrollRect.size.height = Platform::Maximum(1, height - scrollBarFixedSize); +        } else { +            scrollRect.size.height = height; +        } + +        HIViewSetFrame( vScrollBar, &scrollRect ); +        if (HIViewGetSuperview(vScrollBar) == NULL) { +            HIViewSetDrawingEnabled( vScrollBar, true ); +            HIViewSetVisible(vScrollBar, true); +            HIViewAddSubview(GetViewRef(), vScrollBar ); +            Draw1Control(vScrollBar); +        } +    } else if (HIViewGetSuperview(vScrollBar) != NULL) { +        HIViewSetDrawingEnabled( vScrollBar, false ); +        HIViewRemoveFromSuperview(vScrollBar); +    } + +    if (showSBHorizontal) { +        scrollRect.origin.x = 0; +        // Always draw the scrollbar to avoid the "potiential" horizontal scroll bar and to avoid the resize box. +        // This should be "good enough". Best would be to avoid the resize box. +        // Even better would be to embed Scintilla inside an HIScrollView, which would handle this for us. +        scrollRect.origin.y = height - scrollBarFixedSize; +        if (verticalScrollBarVisible) { +            scrollRect.size.width = Platform::Maximum( 1, width - scrollBarFixedSize ); +        } else { +            scrollRect.size.width = width; +        } +        scrollRect.size.height = scrollBarFixedSize; + +        HIViewSetFrame( hScrollBar, &scrollRect ); +        if (HIViewGetSuperview(hScrollBar) == NULL) { +            HIViewSetDrawingEnabled( hScrollBar, true ); +            HIViewAddSubview( GetViewRef(), hScrollBar ); +            Draw1Control(hScrollBar); +        } +    } else  if (HIViewGetSuperview(hScrollBar) != NULL) { +        HIViewSetDrawingEnabled( hScrollBar, false ); +        HIViewRemoveFromSuperview(hScrollBar); +    } + +    ChangeSize(); +} + +void ScintillaMacOSX::NotifyChange() { +    // TODO: How should this be implemented on OS X? Should it be? +} + +pascal void ScintillaMacOSX::LiveScrollHandler( HIViewRef control, SInt16 part ) +{ +    SInt16 currentValue = GetControl32BitValue( control ); +    SInt16 min = GetControl32BitMinimum( control ); +    SInt16 max = GetControl32BitMaximum( control ); +    SInt16 page = GetControlViewSize( control ); + +    // Get a reference to the Scintilla C++ object +    ScintillaMacOSX* scintilla = NULL; +    OSStatus err; +    err = GetControlProperty( control, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla ); +    assert( err == noErr && scintilla != NULL ); + +    int singleScroll = 0; +    if ( control == scintilla->vScrollBar ) +    { +        // Vertical single scroll = one line +        // TODO: Is there a Scintilla preference for this somewhere? +        singleScroll = 1; +    } else { +        assert( control == scintilla->hScrollBar ); +        // Horizontal single scroll = 20 pixels (hardcoded from ScintillaWin) +        // TODO: Is there a Scintilla preference for this somewhere? +        singleScroll = 20; +    } + +    // Determine the new value +    int newValue = 0; +    switch ( part ) +    { +    case kControlUpButtonPart: +        newValue = Platform::Maximum( currentValue - singleScroll, min ); +        break; + +    case kControlDownButtonPart: +        // the the user scrolls to the right, allow more scroll space +        if ( control == scintilla->hScrollBar && currentValue >= max) { +          // change the max value +          scintilla->scrollWidth += singleScroll; +          SetControl32BitMaximum( control, +                           Platform::Maximum( scintilla->scrollWidth - scintilla->GetTextRectangle().Width(), 0 ) ); +          max = GetControl32BitMaximum( control ); +          scintilla->SetScrollBars(); +        } +        newValue =  Platform::Minimum( currentValue + singleScroll, max ); +        break; + +    case kControlPageUpPart: +        newValue = Platform::Maximum( currentValue - page, min ); +        break; + +    case kControlPageDownPart: +        newValue = Platform::Minimum( currentValue + page, max ); +        break; + +    case kControlIndicatorPart: +        newValue = currentValue; +        break; + +    default: +        assert( false ); +        return; +    } + +    // Set the new value +    if ( control == scintilla->vScrollBar ) +    { +        scintilla->ScrollTo( newValue ); +    } else { +        assert( control == scintilla->hScrollBar ); +        scintilla->HorizontalScrollTo( newValue ); +    } +} + +bool ScintillaMacOSX::ScrollBarHit(HIPoint location) { +	// is this on our scrollbars?  If so, track them +	HIViewRef view; +	// view is null if on editor, otherwise on scrollbar +	HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()), +                            &location, true, &view); +	if (view) { +		HIViewPartCode part; + +		// make the point local to a scrollbar  +                PRectangle client = GetClientRectangle(); +		if (view == vScrollBar) { +			location.x -= client.Width(); +		} else if (view == hScrollBar) { +			location.y -= client.Height(); +		} else { +			fprintf(stderr, "got a subview hit, but not a scrollbar???\n"); +                        return false; +		} +                 +		HIViewGetPartHit(view, &location, &part); +	 +		switch (part) +		{ +			case kControlUpButtonPart: +			case kControlDownButtonPart: +			case kControlPageUpPart: +			case kControlPageDownPart: +			case kControlIndicatorPart: +                                ::Point p; +                                p.h = location.x; +                                p.v = location.y; +				// We are assuming Appearance 1.1 or later, so we +				// have the "live scroll" variant of the scrollbar, +				// which lets you pass the action proc to TrackControl +				// for the thumb (this was illegal in previous +				// versions of the defproc). +				isTracking = true; +				::TrackControl(view, p, ScintillaMacOSX::LiveScrollHandler); +				::HiliteControl(view, 0); +				isTracking = false; +				// The mouseup was eaten by TrackControl, however if we +				// do not get a mouseup in the scintilla xbl widget, +				// many bad focus issues happen.  Simply post a mouseup +				// and this firey pit becomes a bit cooler. +				PostEvent(mouseUp, 0); +				break; +			default: +				fprintf(stderr, "PlatformScrollBarHit part %d\n", part); +		} +		return true; +	} +	return false; +} + + +void ScintillaMacOSX::NotifyFocus(bool /*focus*/) { +    // TODO: How should this be implemented on OS X? Should it be? +} + +typedef void (*SciNotifyFunc)(sptr_t *, long); +void ScintillaMacOSX::NotifyParent(SCNotification scn) { +    OSStatus err; +    sptr_t *ptr = NULL; +    SciNotifyFunc fn = NULL; + +    // XXX do this at some other point, or otherwise cache the results +    err = GetControlProperty(GetViewRef(),  +                             scintillaNotifyObject, 0, +                             sizeof( sptr_t * ), NULL, &ptr ); +    if (err != noErr) return; +    err = GetControlProperty(GetViewRef(),  +                             scintillaNotifyFN, 0, +                             sizeof( SciNotifyFunc ), NULL, &fn ); +    if (err != noErr || !fn) return; + +    scn.nmhdr.hwndFrom = GetViewRef(); +    scn.nmhdr.idFrom = (unsigned int)wMain.GetID(); +    fn(ptr, (long int)&scn); +} + +void ScintillaMacOSX::NotifyKey(int key, int modifiers) { +    SCNotification scn; +    scn.nmhdr.code = SCN_KEY; +    scn.ch = key; +    scn.modifiers = modifiers; + +    NotifyParent(scn); +} + +void ScintillaMacOSX::NotifyURIDropped(const char *list) { +    SCNotification scn; +    scn.nmhdr.code = SCN_URIDROPPED; +    scn.text = list; + +    NotifyParent(scn); +} + +int ScintillaMacOSX::KeyDefault(int key, int modifiers) { +    if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT) && (key < 256)) { +        AddChar(key); +        return 1; +    } else { +        // Pass up to container in case it is an accelerator +        NotifyKey(key, modifiers); +        return 0; +    } +    //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers); +} + +template <class T, class U> +struct StupidMap +{ +public: +    T key; +    U value; +}; + +template <class T, class U> +inline static U StupidMapFindFunction( const StupidMap<T, U>* elements, size_t length, const T& desiredKey ) +{ +    for ( size_t i = 0; i < length; ++ i ) +    { +        if ( elements[i].key == desiredKey ) +        { +            return elements[i].value; +        } +    } + +    return NULL; +} + +// NOTE: If this macro is used on a StupidMap that isn't defined by StupidMap x[] = ... +// The size calculation will fail! +#define StupidMapFind( x, y ) StupidMapFindFunction( x, sizeof(x)/sizeof(*x), y ) + +pascal OSStatus ScintillaMacOSX::CommandEventHandler( EventHandlerCallRef /*inCallRef*/, EventRef event, void* data ) +{ +    // TODO: Verify automatically that each constant only appears once? +    const StupidMap<UInt32, void (ScintillaMacOSX::*)()> processCommands[] = { +        { kHICommandCopy, &ScintillaMacOSX::Copy }, +        { kHICommandPaste, &ScintillaMacOSX::Paste }, +        { kHICommandCut, &ScintillaMacOSX::Cut }, +        { kHICommandUndo, &ScintillaMacOSX::Undo }, +        { kHICommandRedo, &ScintillaMacOSX::Redo }, +        { kHICommandClear, &ScintillaMacOSX::ClearSelection }, +        { kHICommandSelectAll, &ScintillaMacOSX::SelectAll }, +    }; +    const StupidMap<UInt32, bool (ScintillaMacOSX::*)()> canProcessCommands[] = { +        { kHICommandCopy, &ScintillaMacOSX::HasSelection }, +        { kHICommandPaste, &ScintillaMacOSX::CanPaste }, +        { kHICommandCut, &ScintillaMacOSX::HasSelection }, +        { kHICommandUndo, &ScintillaMacOSX::CanUndo }, +        { kHICommandRedo, &ScintillaMacOSX::CanRedo }, +        { kHICommandClear, &ScintillaMacOSX::HasSelection }, +        { kHICommandSelectAll, &ScintillaMacOSX::AlwaysTrue }, +    }; +     +    HICommand command;   +    OSStatus result = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( command ), NULL, &command ); +    assert( result == noErr ); + +    UInt32 kind = GetEventKind( event ); +    Platform::DebugPrintf("ScintillaMacOSX::CommandEventHandler kind %d\n", kind); + +    ScintillaMacOSX* scintilla = reinterpret_cast<ScintillaMacOSX*>( data ); +    assert( scintilla != NULL ); +     +    if ( kind == kEventProcessCommand ) +    { +        // Find the method pointer that matches this command +        void (ScintillaMacOSX::*methodPtr)() = StupidMapFind( processCommands, command.commandID ); + +        if ( methodPtr != NULL ) +        { +            // Call the method if we found it, and tell the caller that we handled this event +            (scintilla->*methodPtr)(); +            result = noErr; +        } else { +            // tell the caller that we did not handle the event +            result = eventNotHandledErr; +        } +    } +    // The default Mac OS X text editor does not handle these events to enable/disable menu items +    // Why not? I think it should, so Scintilla does. +    else if ( kind == kEventCommandUpdateStatus && ( command.attributes & kHICommandFromMenu ) ) +    { +        // Find the method pointer that matches this command +        bool (ScintillaMacOSX::*methodPtr)() = StupidMapFind( canProcessCommands, command.commandID ); + +        if ( methodPtr != NULL ) { +            // Call the method if we found it: enabling/disabling menu items +            if ( (scintilla->*methodPtr)() ) { +                EnableMenuItem( command.menu.menuRef, command.menu.menuItemIndex ); +            } else { +                DisableMenuItem( command.menu.menuRef, command.menu.menuItemIndex ); +            } +            result = noErr; +        } else { +            // tell the caller that we did not handle the event +            result = eventNotHandledErr; +        } +    } else { +        // Unhandled event: We should never get here +        assert( false ); +        result = eventNotHandledErr; +    } +     +    return result; +} + +bool ScintillaMacOSX::HasSelection() +{ +    return ( SelectionEnd() - SelectionStart() > 0 ); +} + +bool ScintillaMacOSX::CanUndo() +{ +    return pdoc->CanUndo(); +} + +bool ScintillaMacOSX::CanRedo() +{ +    return pdoc->CanRedo(); +} + +bool ScintillaMacOSX::AlwaysTrue() +{ +    return true; +} + +void ScintillaMacOSX::CopyToClipboard(const SelectionText &selectedText) { +    if (selectedText.len == 0) +        return; + +    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); + +    // Create a CFString from the ASCII/UTF8 data, convert it to UTF16 +    CFStringRef string = CFStringCreateWithBytes( NULL, reinterpret_cast<UInt8*>( selectedText.s ), selectedText.len - 1, encoding, false ); +    assert( string != NULL ); + +    CFIndex numUniChars = CFStringGetLength( string ); +    UniChar* buffer = new UniChar[ numUniChars ]; +    CFStringGetCharacters( string, CFRangeMake( 0, numUniChars ), buffer ); + +    // Done with the CFString +    CFRelease( string ); +    string = NULL; + +    OSStatus err; +    err = ClearCurrentScrap(); +    assert( err == noErr ); + +    ScrapRef scrap = NULL; +    err = GetCurrentScrap( &scrap ); +    assert( err == noErr && scrap != NULL ); + +    err = PutScrapFlavor( scrap, kScrapFlavorTypeUnicode, 0, sizeof( UniChar ) * numUniChars, buffer ); +    assert( err == noErr ); +    err = PutScrapFlavor( scrap, kScrapFlavorTypeText, 0, sizeof( char ) * selectedText.len, reinterpret_cast<UInt8*>( selectedText.s ) ); +    assert( err == noErr ); + +    // Done with the UniChar* buffer +    delete[] buffer; +    buffer = NULL;   +} + +void ScintillaMacOSX::Copy() +{ +    if (currentPos != anchor) { +        SelectionText selectedText; +        CopySelectionRange(&selectedText); +        CopyToClipboard(selectedText); +    } +} + +bool ScintillaMacOSX::CanPaste() +{ +    ScrapRef scrap = NULL; +    OSStatus err; +    err = GetCurrentScrap( &scrap ); +    assert( err == noErr && scrap != NULL ); +     +    ScrapFlavorFlags flavorFlags; +    return GetScrapFlavorFlags ( scrap, kScrapFlavorTypeUnicode, &flavorFlags ) == noErr || +          GetScrapFlavorFlags ( scrap, kScrapFlavorTypeText, &flavorFlags ) == noErr; +} + +void ScintillaMacOSX::Paste() +{ +    Paste(false); +} + +// XXX there is no system flag (I can find) to tell us that a paste is rectangular, so  +//     applications must implement an additional command (eg. option-V like BBEdit) +//     in order to provide rectangular paste +void ScintillaMacOSX::Paste(bool isRectangular) +{ +    // Make sure that we CAN paste +    if ( ! CanPaste() ) return; + +    // Get the clipboard reference +    ScrapRef scrap = NULL; +    OSStatus err; +    err = GetCurrentScrap( &scrap ); +    assert( err == noErr && scrap != NULL ); + +    ScrapFlavorFlags flavorFlags; +    Size bytes = 0; +    CFStringRef string = NULL; +    if (GetScrapFlavorFlags ( scrap, kScrapFlavorTypeUnicode, &flavorFlags ) == noErr) +    { +        // No error, we have unicode data in a Scrap. Find out how many bytes of data it is. +        err = GetScrapFlavorSize( scrap, kScrapFlavorTypeUnicode, &bytes ); +        assert( err == noErr && bytes != 0 ); +        Size numUniChars = bytes / sizeof( UniChar ); +     +        // Allocate a buffer for the text using Core Foundation +        UniChar* buffer = reinterpret_cast<UniChar*>( CFAllocatorAllocate( NULL, bytes, 0 ) ); +        assert( buffer != NULL ); +     +        // Get a copy of the text +        Size nextBytes = bytes; +        err = GetScrapFlavorData( scrap, kScrapFlavorTypeUnicode, &nextBytes, buffer ); +        assert( err == noErr && nextBytes == bytes ); +     +        // Create a CFString which wraps and takes ownership of the buffer +        string = CFStringCreateWithCharactersNoCopy( NULL, buffer, numUniChars, NULL ); +        assert( string != NULL ); +        buffer = NULL; // string now owns this buffer +    } else if (GetScrapFlavorFlags ( scrap, kScrapFlavorTypeText, &flavorFlags ) == noErr) { +        // No error, we have unicode data in a Scrap. Find out how many bytes of data it is. +        err = GetScrapFlavorSize( scrap, kScrapFlavorTypeText, &bytes ); +        assert( err == noErr && bytes != 0 ); +     +        // Allocate a buffer for the text using Core Foundation +        char* buffer = reinterpret_cast<char*>( CFAllocatorAllocate( NULL, bytes + 1, 0 ) ); +        assert( buffer != NULL ); +     +        // Get a copy of the text +        Size nextBytes = bytes; +        err = GetScrapFlavorData( scrap, kScrapFlavorTypeText, &nextBytes, buffer ); +        assert( err == noErr && nextBytes == bytes ); +        buffer[bytes]=0; +        // Create a CFString which wraps and takes ownership of the buffer +        string = CFStringCreateWithCStringNoCopy( NULL, buffer, kCFStringEncodingMacRoman, NULL ); +        assert( string != NULL ); +        buffer = NULL; // string now owns this buffer +    } else { +        // a flavor we do not understand +        return; +    } + + +    // Allocate a buffer, plus the null byte +    CFIndex numUniChars = CFStringGetLength( string ); +    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); +    CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; +    char* cstring = new char[maximumByteLength]; +    CFIndex usedBufferLength = 0; +    CFIndex numCharsConverted; +    numCharsConverted = CFStringGetBytes( string, CFRangeMake( 0, numUniChars ), encoding, +                              '?', false, reinterpret_cast<UInt8*>( cstring ), +                              maximumByteLength, &usedBufferLength ); +    cstring[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string +    assert( numCharsConverted == numUniChars ); + +    // Default allocator releases both the CFString and the UniChar buffer (text) +    CFRelease( string ); +    string = NULL;       + +    // determine whether a BOM is in the string.  Apps like Emacs prepends a BOM +    // to the string, CFStrinGetBytes reflects that (though it may change in the conversion) +    // so we need to remove it before pasting into our buffer.  TextWrangler has no +    // problem dealing with BOM when pasting into it. +    int bomLen = BOMlen((unsigned char *)cstring); + +    // convert line endings to the document line ending +    int newlen = 0; +    char *pasted = Document::TransformLineEnds(&newlen, +                                                cstring + bomLen, +                                                usedBufferLength - bomLen, +                                                pdoc->eolMode); +     +    pdoc->BeginUndoAction(); +    ClearSelection(); + +    if (isRectangular) { +        int selStart = SelectionStart(); +        PasteRectangular(selStart, pasted, newlen); +    } else  +    if ( pdoc->InsertString( currentPos, pasted, newlen ) ) { +        SetEmptySelection( currentPos + newlen ); +    } + +    delete[] pasted; +    delete[] cstring; +    cstring = NULL; +     +    pdoc->EndUndoAction(); +    NotifyChange(); +    Redraw(); +} + +void ScintillaMacOSX::CreateCallTipWindow(PRectangle rc) { +    // create a calltip window +    if (!ct.wCallTip.Created()) { +        WindowClass windowClass = kHelpWindowClass; +        WindowAttributes attributes = kWindowNoAttributes; +        Rect contentBounds; +        WindowRef outWindow; + +        // convert PRectangle to Rect +        // this adjustment gets the calltip window placed in the correct location relative +        // to our editor window +        Rect bounds; +        OSStatus err; +        err = GetWindowBounds( this->GetOwner(), kWindowGlobalPortRgn, &bounds ); +        assert( err == noErr ); +        contentBounds.top = rc.top + bounds.top; +        contentBounds.bottom = rc.bottom + bounds.top; +        contentBounds.right = rc.right + bounds.left; +        contentBounds.left = rc.left + bounds.left; + +        // create our calltip hiview +        HIViewRef ctw = scintilla_calltip_new(); +        CallTip* objectPtr = &ct; +        ScintillaMacOSX* sciThis = this; +        SetControlProperty( ctw, scintillaMacOSType, 0, sizeof( this ), &sciThis ); +        SetControlProperty( ctw, scintillaCallTipType, 0, sizeof( objectPtr ), &objectPtr ); + +        CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow); +        ControlRef root; +        CreateRootControl(outWindow, &root); + +        HIViewRef hiroot = HIViewGetRoot (outWindow); +        HIViewAddSubview(hiroot, ctw); + +        HIRect boundsRect; +        HIViewGetFrame(hiroot, &boundsRect); +        HIViewSetFrame( ctw, &boundsRect ); + +        // bind the size of the calltip to the size of it's container window +        HILayoutInfo layout = { +            kHILayoutInfoVersionZero, +            { +              { NULL, kHILayoutBindTop, 0 }, +              { NULL, kHILayoutBindLeft, 0 }, +              { NULL, kHILayoutBindBottom, 0 }, +              { NULL, kHILayoutBindRight, 0 } +            }, +            { +                { NULL, kHILayoutScaleAbsolute, 0 }, +                { NULL, kHILayoutScaleAbsolute, 0 } + +            }, +            { +                { NULL, kHILayoutPositionTop, 0 }, +                { NULL, kHILayoutPositionLeft, 0 } +            } +        }; +        HIViewSetLayoutInfo(ctw, &layout); + +        ct.wCallTip = root; +        ct.wDraw = ctw; +        ct.wCallTip.SetWindow(outWindow); +        HIViewSetVisible(ctw,true); + +    } +} + +void ScintillaMacOSX::CallTipClick()  +{ +    ScintillaBase::CallTipClick(); +} + +void ScintillaMacOSX::AddToPopUp( const char *label, int cmd, bool enabled ) +{ +    // Translate stuff into menu item attributes +    MenuItemAttributes attributes = 0; +    if ( label[0] == '\0' ) attributes |= kMenuItemAttrSeparator; +    if ( ! enabled ) attributes |= kMenuItemAttrDisabled; + +    // Translate Scintilla commands into Mac OS commands +    // TODO: If I create an AEDesc, OS X may insert these standard +    // text editing commands into the menu for me +    MenuCommand macCommand; +    switch( cmd ) +    { +    case idcmdUndo: +        macCommand = kHICommandUndo; +        break; +    case idcmdRedo: +        macCommand = kHICommandRedo; +        break; +    case idcmdCut: +        macCommand = kHICommandCut; +        break; +    case idcmdCopy: +        macCommand = kHICommandCopy; +        break; +    case idcmdPaste: +        macCommand = kHICommandPaste; +        break; +    case idcmdDelete: +        macCommand = kHICommandClear; +        break; +    case idcmdSelectAll: +        macCommand = kHICommandSelectAll; +        break; +    case 0: +        macCommand = 0; +        break; +    default: +        assert( false ); +        return; +    } + +    CFStringRef string = CFStringCreateWithCString( NULL, label, kTextEncodingMacRoman ); +    OSStatus err; +    err = AppendMenuItemTextWithCFString( reinterpret_cast<MenuRef>( popup.GetID() ), +                               string, attributes, macCommand, NULL ); +    assert( err == noErr ); + +    CFRelease( string ); +    string = NULL; +} + +void ScintillaMacOSX::ClaimSelection() { +    // Mac OS X does not have a primary selection +} + +/** A wrapper function to permit external processes to directly deliver messages to our "message loop". */ +sptr_t ScintillaMacOSX::DirectFunction( +    ScintillaMacOSX *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { +    return sciThis->WndProc(iMessage, wParam, lParam); +} + +sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) { +        HIViewRef control = reinterpret_cast<HIViewRef>(sci); +    // Platform::DebugPrintf("scintilla_send_message %08X control %08X\n",sci,control); +    // Get a reference to the Scintilla C++ object +    ScintillaMacOSX* scintilla = NULL; +    OSStatus err; +    err = GetControlProperty( control, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla ); +    assert( err == noErr && scintilla != NULL ); +    //Platform::DebugPrintf("scintilla_send_message scintilla %08X\n",scintilla); + +    return scintilla->WndProc(iMessage, wParam, lParam); +} + +void ScintillaMacOSX::TimerFired( EventLoopTimerRef ) +{ +    Tick(); +    DragScroll(); +} + +OSStatus ScintillaMacOSX::BoundsChanged( UInt32 /*inOptions*/, const HIRect& inOriginalBounds, const HIRect& inCurrentBounds, RgnHandle /*inInvalRgn*/ ) +{ +    // If the width or height changed, modify the scroll bars and notify Scintilla +    // This event is also delivered when the window moves, and we don't care about that +    if ( inOriginalBounds.size.width != inCurrentBounds.size.width || inOriginalBounds.size.height != inCurrentBounds.size.height ) +    { +        Resize( static_cast<int>( inCurrentBounds.size.width ), static_cast<int>( inCurrentBounds.size.height ) ); +    } +    return noErr; +} + +void ScintillaMacOSX::Draw( RgnHandle rgn, CGContextRef gc ) +{ +    Rect invalidRect; +    GetRegionBounds( rgn, &invalidRect ); + +    // NOTE: We get draw events that include the area covered by the scroll bar. No fear: Scintilla correctly ignores them +    SyncPaint( gc, PRectangle( invalidRect.left, invalidRect.top, invalidRect.right, invalidRect.bottom ) ); +} + +ControlPartCode ScintillaMacOSX::HitTest( const HIPoint& where ) +{ +    if ( CGRectContainsPoint( Bounds(), where ) ) +        return 1; +    else +        return kControlNoPart; +} + +OSStatus ScintillaMacOSX::SetFocusPart( ControlPartCode desiredFocus, RgnHandle /*invalidRgn*/, Boolean /*inFocusEverything*/, ControlPartCode* outActualFocus ) +{ +    assert( outActualFocus != NULL ); + +    if ( desiredFocus == 0 ) { +        // We are losing the focus +        SetFocusState(false); +    } else { +        // We are getting the focus +        SetFocusState(true); +    } +     +    *outActualFocus = desiredFocus; +    return noErr; +} + +// Map Mac Roman character codes to their equivalent Scintilla codes +static inline int KeyTranslate( UniChar unicodeChar ) +{ +    switch ( unicodeChar ) +    { +    case kDownArrowCharCode: +        return SCK_DOWN; +    case kUpArrowCharCode: +        return SCK_UP; +    case kLeftArrowCharCode: +        return SCK_LEFT; +    case kRightArrowCharCode: +        return SCK_RIGHT; +    case kHomeCharCode: +        return SCK_HOME; +    case kEndCharCode: +        return SCK_END; +    case kPageUpCharCode: +        return SCK_PRIOR; +    case kPageDownCharCode: +        return SCK_NEXT; +    case kDeleteCharCode: +        return SCK_DELETE; +    // TODO: Is there an insert key in the mac world? My insert key is the "help" key +    case kHelpCharCode: +        return SCK_INSERT; +    case kEnterCharCode: +    case kReturnCharCode: +        return SCK_RETURN; +    case kEscapeCharCode: +        return SCK_ESCAPE; +    case kBackspaceCharCode: +        return SCK_BACK; +    case '\t': +         return SCK_TAB; +    case '+': +        return SCK_ADD; +    case '-': +        return SCK_SUBTRACT; +    case '/': +        return SCK_DIVIDE; +    case kFunctionKeyCharCode: +        return kFunctionKeyCharCode; +    default: +        return 0; +    } +} + +static inline UniChar GetCharacterWithoutModifiers( EventRef rawKeyboardEvent ) +{ +    UInt32 keyCode; +    // Get the key code from the raw key event +    GetEventParameter( rawKeyboardEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof( keyCode ), NULL, &keyCode ); + +    // Get the current keyboard layout + // TODO: If this is a performance sink, we need to cache these values +    SInt16 lastKeyLayoutID = GetScriptVariable( /*currentKeyScript*/ GetScriptManagerVariable(smKeyScript), smScriptKeys); +    Handle uchrHandle = GetResource('uchr', lastKeyLayoutID); + +    // Translate the key press ignoring ctrl and option +    UInt32 ignoredDeadKeys = 0; +    UInt32 ignoredActualLength = 0; +    UniChar unicodeKey = 0; +    // (((modifiers & shiftKey) >> 8) & 0xFF) +    OSStatus err; +    err = UCKeyTranslate( reinterpret_cast<UCKeyboardLayout*>( *uchrHandle ), keyCode, kUCKeyActionDown, +                                /* modifierKeyState */ 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &ignoredDeadKeys, +                                /* buffer length */ 1, +                                /* actual length */ &ignoredActualLength, +                                /* string */ &unicodeKey ); +    assert( err == noErr ); + +    return unicodeKey; +} + +// Text input is very annoying: +// If the control key is pressed, or if the key is a "special" key (eg. arrow keys, function keys, whatever) +//  we let Scintilla handle it. If scintilla does not handle it, we do nothing (eventNotHandledErr). +// Otherwise, the event is just some text and we add it to the buffer +OSStatus ScintillaMacOSX::TextInput( TCarbonEvent& event ) +{ +    // Obtain the number of bytes of text +    UInt32 actualSize = 0; +    OSStatus err; +    err = event.GetParameterSize( kEventParamTextInputSendText, &actualSize ); +    assert( err == noErr ); +    assert( actualSize != 0 ); + +    const int numUniChars = actualSize / sizeof( UniChar ); + +    // Allocate a buffer for the text using Core Foundation +    UniChar* text = reinterpret_cast<UniChar*>( CFAllocatorAllocate( CFAllocatorGetDefault(), actualSize, 0 ) ); +    assert( text != NULL ); + +    // Get a copy of the text +    err = event.GetParameter( kEventParamTextInputSendText, typeUnicodeText, actualSize, text ); +    assert( err == noErr ); + +    // TODO: This is a gross hack to ignore function keys +    // Surely we can do better? +    if ( numUniChars == 1 && text[0] == kFunctionKeyCharCode ) return eventNotHandledErr; +    int modifiers = GetCurrentEventKeyModifiers(); +    int scintillaKey = KeyTranslate( text[0] ); + +    // Create a CFString which wraps and takes ownership of the "text" buffer +    CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, text, numUniChars, NULL ); +    assert( string != NULL ); +    //delete text; +    text = NULL; + +    // If we have a single unicode character that is special or  +    // to process a command. Try to do some translation. +    if ( numUniChars == 1 && ( modifiers & controlKey || scintillaKey != 0 ) ) { +        // If we have a modifier, we need to get the character without modifiers +        if ( modifiers & controlKey ) { +            EventRef rawKeyboardEvent = NULL; +            event.GetParameter( +                      kEventParamTextInputSendKeyboardEvent, +                      typeEventRef, +                      sizeof( EventRef ), +                      &rawKeyboardEvent ); +            assert( rawKeyboardEvent != NULL ); +            scintillaKey = GetCharacterWithoutModifiers( rawKeyboardEvent ); + +            // Make sure that we still handle special characters correctly +            int temp = KeyTranslate( scintillaKey ); +            if ( temp != 0 ) scintillaKey = temp; + +            // TODO: This is a gross Unicode hack: ASCII chars have a value < 127 +            if ( scintillaKey <= 127 ) { +                scintillaKey = toupper( (char) scintillaKey ); +            } +        } +             +        // Code taken from Editor::KeyDown +        // It is copied here because we don't want to feed the key via +        // KeyDefault if there is no special action +        DwellEnd(false); +        int scintillaModifiers = ( (modifiers & shiftKey) ? SCI_SHIFT : 0) | ( (modifiers & controlKey) ? SCI_CTRL : 0) | +            ( (modifiers & optionKey) ? SCI_ALT : 0); +        int msg = kmap.Find( scintillaKey, scintillaModifiers ); +        if (msg) { +            // The keymap has a special event for this key: perform the operation +            WndProc(msg, 0, 0); +            err = noErr; +        } else { +            // We do not handle this event +            err = eventNotHandledErr; +        } +    } else { +        CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); + +        // Allocate the buffer (don't forget the null!) +        CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; +        char* buffer = new char[maximumByteLength]; + +        CFIndex usedBufferLength = 0; +        CFIndex numCharsConverted; +        numCharsConverted = CFStringGetBytes( string, CFRangeMake( 0, numUniChars ), encoding, +                                                '?', false, reinterpret_cast<UInt8*>( buffer ), +                                                maximumByteLength, &usedBufferLength ); +        assert( numCharsConverted == numUniChars ); +        buffer[usedBufferLength] = '\0'; // null terminate +         +        // Add all the characters to the document +        // NOTE: OS X doesn't specify that text input events provide only a single character +        // if we get a single character, add it as a character +        // otherwise, we insert the entire string +        if ( numUniChars == 1 ) { +            AddCharUTF( buffer, usedBufferLength ); +        } else { +            // WARNING: This is an untested code path as with my US keyboard, I only enter a single character at a time +            if (pdoc->InsertString(currentPos, buffer, usedBufferLength)) { +                SetEmptySelection(currentPos + usedBufferLength); +            } +        } + +        // Free the buffer that was allocated +        delete[] buffer; +        buffer = NULL; +        err = noErr; +    } + +    // Default allocator releases both the CFString and the UniChar buffer (text) +    CFRelease( string ); +    string = NULL;   +     +    return err; +} + +UInt32 ScintillaMacOSX::GetBehaviors() +{ +    return TView::GetBehaviors() | kControlGetsFocusOnClick | kControlSupportsEmbedding; +} + +OSStatus ScintillaMacOSX::MouseEntered(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ) +{ +    if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) { +        HIViewRef view; +        HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()), &location, true, &view); +        if (view) { +            // the hit is on a subview (ie. scrollbars) +            WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); +        } else { +            // reset to normal, buttonmove will change for other area's in the editor +            WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0); +        } +        return noErr; +    } +    return eventNotHandledErr; +} + +OSStatus ScintillaMacOSX::MouseExited(HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ) +{ +    if (HIViewGetSuperview(GetViewRef()) != NULL) { +        if (HaveMouseCapture()) { +            ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ), +                      static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),  +                      (modifiers & controlKey) != 0 ); +        } +        WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); +        return noErr; +    } +    return eventNotHandledErr; +} + + +OSStatus ScintillaMacOSX::MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount , TCarbonEvent& inEvent) +{ +    ConvertEventRefToEventRecord( inEvent.GetEventRef(), &mouseDownEvent ); +    return MouseDown(location, modifiers, button, clickCount); +} + +OSStatus ScintillaMacOSX::MouseDown( EventRecord *event ) +{ +    HIPoint pt = GetLocalPoint(event->where); +    int button = kEventMouseButtonPrimary; +    mouseDownEvent = *event; +   +    if ( event->modifiers & controlKey ) +        button = kEventMouseButtonSecondary; +    return MouseDown(pt, event->modifiers, button, 1); +} + +OSStatus ScintillaMacOSX::MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 /*clickCount*/ ) +{ +    // We only deal with the first mouse button +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +    // TODO: Verify that Scintilla wants the time in milliseconds +    if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) { +        if (ScrollBarHit(location)) return noErr; +    } +    ButtonDown( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ), +             static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ), +             (modifiers & shiftKey) != 0,  +             (modifiers & controlKey) != 0,  +             (modifiers & cmdKey) ); +#if !defined(CONTAINER_HANDLES_EVENTS) +    OSStatus err; +    err = SetKeyboardFocus( this->GetOwner(), this->GetViewRef(), 1 ); +    assert( err == noErr ); +    return noErr; +#else +    return eventNotHandledErr; // allow event to go to container +#endif +} + +OSStatus ScintillaMacOSX::MouseUp( EventRecord *event ) +{ +    HIPoint pt = GetLocalPoint(event->where); +    int button = kEventMouseButtonPrimary; +    if ( event->modifiers & controlKey ) +        button = kEventMouseButtonSecondary; +    return MouseUp(pt, event->modifiers, button, 1); +} + +OSStatus ScintillaMacOSX::MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 /*clickCount*/ ) +{ +    // We only deal with the first mouse button +    if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr; +        ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ), +               static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),  +               (modifiers & controlKey) != 0 ); +     +#if !defined(CONTAINER_HANDLES_EVENTS) +    return noErr; +#else +    return eventNotHandledErr; // allow event to go to container +#endif +} + +OSStatus ScintillaMacOSX::MouseDragged( EventRecord *event ) +{ +    HIPoint pt = GetLocalPoint(event->where); +    int button = 0; +    if ( event->modifiers & btnStateBit ) { +        button = kEventMouseButtonPrimary; +        if ( event->modifiers & controlKey ) +            button = kEventMouseButtonSecondary; +    } +    return MouseDragged(pt, event->modifiers, button, 1); +} + +OSStatus ScintillaMacOSX::MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ) +{ +#if !defined(CONTAINER_HANDLES_EVENTS) +    ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) ); +    return noErr; +#else +    if (HaveMouseCapture() && !inDragDrop) { +        MouseTrackingResult mouseStatus = 0; +        ::Point theQDPoint; +        UInt32 outModifiers; +        EventTimeout inTimeout=0.1; +        while (mouseStatus != kMouseTrackingMouseReleased) { +            ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) ); +            TrackMouseLocationWithOptions((GrafPtr)-1, +                                          kTrackMouseLocationOptionDontConsumeMouseUp, +                                          inTimeout, +                                          &theQDPoint, +                                          &outModifiers, +                                          &mouseStatus); +            location = GetLocalPoint(theQDPoint); +        } +        ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ), +                  static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),  +                  (modifiers & controlKey) != 0 ); +    } else { +        if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) { +            HIViewRef view; +            HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()), &location, true, &view); +            if (view) { +                // the hit is on a subview (ie. scrollbars) +                WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); +                return eventNotHandledErr; +            } else { +                // reset to normal, buttonmove will change for other area's in the editor +                WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0); +            } +        } +        ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) ); +    } +    return eventNotHandledErr; // allow event to go to container +#endif +} + +OSStatus ScintillaMacOSX::MouseWheelMoved( EventMouseWheelAxis axis, SInt32 delta, UInt32 modifiers ) +{ +    if ( axis != 1 ) return eventNotHandledErr; +     +    if ( modifiers & controlKey ) { +        // Zoom! We play with the font sizes in the styles. +        // Number of steps/line is ignored, we just care if sizing up or down +        if ( delta > 0 ) { +            KeyCommand( SCI_ZOOMIN ); +        } else { +            KeyCommand( SCI_ZOOMOUT ); +        } +    } else { +        // Decide if this should be optimized? +        ScrollTo( topLine - delta ); +    } + +    return noErr; +} + +OSStatus ScintillaMacOSX::ContextualMenuClick( HIPoint& location ) +{ +    // convert screen coords to window relative +    Rect bounds; +    OSStatus err; +    err = GetWindowBounds( this->GetOwner(), kWindowContentRgn, &bounds ); +    assert( err == noErr ); +    location.x += bounds.left; +    location.y += bounds.top; +    ContextMenu( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) ); +    return noErr;    +} + +OSStatus ScintillaMacOSX::ActiveStateChanged() +{ +    // If the window is being deactivated, lose the focus and turn off the ticking +    if ( ! this->IsActive() ) { +        DropCaret(); +        //SetFocusState( false ); +        SetTicking( false ); +    } else { +        ShowCaretAtCurrentPosition(); +    } +    return noErr; +} + +HIViewRef ScintillaMacOSX::Create() +{ +    // Register the HIView, if needed +    static bool registered = false; + +    if ( not registered ) { +        TView::RegisterSubclass( kScintillaClassID, Construct ); +        registered = true; +    } + +    OSStatus err = noErr; +    EventRef event = CreateInitializationEvent(); +    assert( event != NULL ); + +    HIViewRef control = NULL; +    err = HIObjectCreate( kScintillaClassID, event, reinterpret_cast<HIObjectRef*>( &control ) ); +    ReleaseEvent( event ); +    if ( err == noErr ) { +        Platform::DebugPrintf("ScintillaMacOSX::Create control %08X\n",control); +        return control; +    } +    return NULL;     +} + +OSStatus ScintillaMacOSX::Construct( HIViewRef inControl, TView** outView ) +{ +    *outView = new ScintillaMacOSX( inControl ); +    Platform::DebugPrintf("ScintillaMacOSX::Construct scintilla %08X\n",*outView); +    if ( *outView != NULL ) +        return noErr; +    else +        return memFullErr;  // could be a lie +} + +extern "C" { +HIViewRef scintilla_new() { +    return ScintillaMacOSX::Create(); +} +} diff --git a/macosx/ScintillaMacOSX.h b/macosx/ScintillaMacOSX.h new file mode 100644 index 000000000..0f02042f5 --- /dev/null +++ b/macosx/ScintillaMacOSX.h @@ -0,0 +1,192 @@ +/* + *  ScintillaMacOSX.h + *  tutorial + * + *  Created by Evan Jones on Sun Sep 01 2002. + *  Copyright (c) 2002 __MyCompanyName__. All rights reserved. + * + */ +#include "TView.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <time.h> + +#include "Platform.h" +#include "Scintilla.h" +#include "PlatMacOSX.h" + + +#include "ScintillaWidget.h" +#ifdef SCI_LEXER +#include "SciLexer.h" +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#endif +#include "ContractionState.h" +#include "SVector.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "CellBuffer.h" +#include "CallTip.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "XPM.h" +#include "LineMarker.h" +#include "Style.h" +#include "AutoComplete.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "Document.h" +#include "Editor.h" +#include "SString.h" +#include "ScintillaBase.h" +#include "ScintillaCallTip.h" + +static const OSType scintillaMacOSType = 'Scin'; +static const OSType scintillaNotifyObject = 'Snob'; +static const OSType scintillaNotifyFN = 'Snfn'; + +namespace Scintilla { + +class ScintillaMacOSX : public ScintillaBase, public TView +{ + public: +    HIViewRef vScrollBar; +    HIViewRef hScrollBar; +    SInt32 scrollBarFixedSize; + +    bool capturedMouse; +    bool inDragSession; // true if scintilla initiated the drag session +    bool isTracking;  + +    // Private so ScintillaMacOSX objects can not be copied +    ScintillaMacOSX(const ScintillaMacOSX &) : ScintillaBase(), TView( NULL ) {} +    ScintillaMacOSX &operator=(const ScintillaMacOSX &) { return * this; } + +public: +    /** This is the class ID that we've assigned to Scintilla. */ +    static const CFStringRef kScintillaClassID; +    static const ControlKind kScintillaKind; + +    ScintillaMacOSX( void* windowid ); +    virtual ~ScintillaMacOSX(); +    //~ static void ClassInit(GtkObjectClass* object_class, GtkWidgetClass *widget_class); + +    /** Returns the HIView object kind, needed to subclass TView. */ +    virtual ControlKind GetKind() { return kScintillaKind; } + +private: +    virtual void Initialise(); +    virtual void Finalise(); +    virtual void StartDrag(); +    Scintilla::Point GetDragPoint(DragRef inDrag); +    OSStatus GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, CFStringRef *textString); +    void SetDragCursor(DragRef inDrag); + +    // Drag and drop +    virtual bool DragEnter(DragRef inDrag ); +    virtual bool DragWithin(DragRef inDrag ); +    virtual bool DragLeave(DragRef inDrag ); +    virtual OSStatus DragReceive(DragRef inDrag ); +    void DragScroll(); +    int scrollSpeed; +    int scrollTicks; + +    EventRecord mouseDownEvent; +    MouseTrackingRef mouseTrackingRef; +    MouseTrackingRegionID mouseTrackingID; +    HIPoint GetLocalPoint(::Point pt); + +    static pascal void IdleTimerEventHandler(EventLoopTimerRef inTimer, +                                             EventLoopIdleTimerMessage inState, +                                             void *scintilla ); + +public: // Public for scintilla_send_message +    virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + +    void SyncPaint( void* gc, PRectangle rc); +    //void FullPaint( void* gc ); +    virtual void Draw( RgnHandle rgn, CGContextRef gc ); + +    virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); +    virtual void SetTicking(bool on); +    virtual bool SetIdle(bool on); +    virtual void SetMouseCapture(bool on); +    virtual bool HaveMouseCapture(); +    virtual PRectangle GetClientRectangle(); + +    virtual void ScrollText(int linesToMove); +    virtual void SetVerticalScrollPos(); +    virtual void SetHorizontalScrollPos(); +    virtual bool ModifyScrollBars(int nMax, int nPage); +    virtual void ReconfigureScrollBars(); +    void Resize(int width, int height); +    static pascal void LiveScrollHandler( ControlHandle control, SInt16 part ); +    bool ScrollBarHit(HIPoint location); +     +    virtual void NotifyChange(); +    virtual void NotifyFocus(bool focus); +    virtual void NotifyParent(SCNotification scn); +    void NotifyKey(int key, int modifiers); +    void NotifyURIDropped(const char *list); +    virtual int KeyDefault(int key, int modifiers); +    static pascal OSStatus CommandEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* data ); + +    bool HasSelection(); +    bool CanUndo(); +    bool CanRedo(); +    bool AlwaysTrue(); +    virtual void CopyToClipboard(const SelectionText &selectedText); +    virtual void Copy(); +    virtual bool CanPaste(); +    virtual void Paste(); +    virtual void Paste(bool rectangular); +    virtual void CreateCallTipWindow(PRectangle rc); +    virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); +    virtual void ClaimSelection(); + +    static sptr_t DirectFunction(ScintillaMacOSX *sciThis, +                                 unsigned int iMessage, uptr_t wParam, sptr_t lParam); + +    /** Timer event handler. Simply turns around and calls Tick. */ +    virtual void TimerFired( EventLoopTimerRef ); +    virtual OSStatus BoundsChanged( UInt32 inOptions, const HIRect& inOriginalBounds, const HIRect& inCurrentBounds, RgnHandle inInvalRgn ); +    virtual ControlPartCode HitTest( const HIPoint& where ); +    virtual OSStatus SetFocusPart( ControlPartCode desiredFocus, RgnHandle, Boolean, ControlPartCode* outActualFocus ); +    virtual OSStatus TextInput( TCarbonEvent& event ); + +    // Configure the features of this control +    virtual UInt32 GetBehaviors(); + +    virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount, TCarbonEvent& inEvent ); +    virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseDown( EventRecord *rec ); +    virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseUp( EventRecord *rec ); +    virtual OSStatus MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseDragged( EventRecord *rec ); +    virtual OSStatus MouseEntered( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseExited( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount ); +    virtual OSStatus MouseWheelMoved( EventMouseWheelAxis axis, SInt32 delta, UInt32 modifiers ); +    virtual OSStatus ContextualMenuClick( HIPoint& location ); + +    virtual OSStatus ActiveStateChanged(); + +    virtual void CallTipClick(); + + +public: +    static HIViewRef Create(); +private: +    static OSStatus Construct( HIViewRef inControl, TView** outView ); +     +}; + + +} diff --git a/macosx/TCarbonEvent.cxx b/macosx/TCarbonEvent.cxx new file mode 100644 index 000000000..eca31e569 --- /dev/null +++ b/macosx/TCarbonEvent.cxx @@ -0,0 +1,519 @@ +/* +    File:		TCarbonEvent.cp +     +    Version:	1.0 + +	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. +				("Apple") in consideration of your agreement to the following terms, and your +				use, installation, modification or redistribution of this Apple software +				constitutes acceptance of these terms.  If you do not agree with these terms, +				please do not use, install, modify or redistribute this Apple software. + +				In consideration of your agreement to abide by the following terms, and subject +				to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs +				copyrights in this original Apple software (the "Apple Software"), to use, +				reproduce, modify and redistribute the Apple Software, with or without +				modifications, in source and/or binary forms; provided that if you redistribute +				the Apple Software in its entirety and without modifications, you must retain +				this notice and the following text and disclaimers in all such redistributions of +				the Apple Software.  Neither the name, trademarks, service marks or logos of +				Apple Computer, Inc. may be used to endorse or promote products derived from the +				Apple Software without specific prior written permission from Apple.  Except as +				expressly stated in this notice, no other rights or licenses, express or implied, +				are granted by Apple herein, including but not limited to any patent rights that +				may be infringed by your derivative works or by other works in which the Apple +				Software may be incorporated. + +				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO +				WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +				WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +				PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +				COMBINATION WITH YOUR PRODUCTS. + +				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +				CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +				GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +				ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +				OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +				(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +				ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +	Copyright © 2002 Apple Computer, Inc., All Rights Reserved +*/ + +#include "TCarbonEvent.h" + +//----------------------------------------------------------------------------------- +//	TCarbonEvent constructor +//----------------------------------------------------------------------------------- +// +TCarbonEvent::TCarbonEvent( +	UInt32				inClass, +	UInt32				inKind ) +{ +	CreateEvent( NULL, inClass, inKind, GetCurrentEventTime(), 0, &fEvent ); +} + +//----------------------------------------------------------------------------------- +//	TCarbonEvent constructor +//----------------------------------------------------------------------------------- +// +TCarbonEvent::TCarbonEvent( +	EventRef			inEvent ) +{ +	fEvent = inEvent; +	RetainEvent( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	TCarbonEvent destructor +//----------------------------------------------------------------------------------- +// +TCarbonEvent::~TCarbonEvent() +{ +	ReleaseEvent( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	GetClass +//----------------------------------------------------------------------------------- +// +UInt32 TCarbonEvent::GetClass() const +{ +	return GetEventClass( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	GetKind +//----------------------------------------------------------------------------------- +// +UInt32 TCarbonEvent::GetKind() const +{ +	return GetEventKind( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	SetTime +//----------------------------------------------------------------------------------- +// +void TCarbonEvent::SetTime( +	EventTime			inTime ) +{ +	SetEventTime( fEvent, inTime ); +} + +//----------------------------------------------------------------------------------- +//	GetTime +//----------------------------------------------------------------------------------- +// +EventTime TCarbonEvent::GetTime() const +{ +	return GetEventTime( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	Retain +//----------------------------------------------------------------------------------- +// +void TCarbonEvent::Retain() +{ +	RetainEvent( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	Release +//----------------------------------------------------------------------------------- +// +void TCarbonEvent::Release() +{ +	ReleaseEvent( fEvent ); +} + +//----------------------------------------------------------------------------------- +//	PostToQueue +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::PostToQueue( +	EventQueueRef		inQueue, +	EventPriority		inPriority ) +{ +	return PostEventToQueue( inQueue, fEvent, inPriority ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	EventParamType		inType, +	UInt32				inSize, +	const void*			inData ) +{ +	return SetEventParameter( fEvent, inName, inType, inSize, inData ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	EventParamType		inType, +	UInt32				inBufferSize, +	void*				outData ) +{ +	return GetEventParameter( fEvent, inName, inType, NULL, inBufferSize, NULL, outData ); +} + +//----------------------------------------------------------------------------------- +//	GetParameterType +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameterType( +	EventParamName		inName, +	EventParamType*		outType ) +{ +	return GetEventParameter( fEvent, inName, typeWildCard, outType, 0, NULL, NULL ); +} + +//----------------------------------------------------------------------------------- +//	GetParameterSize +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameterSize( +	EventParamName		inName, +	UInt32*				outSize ) +{ +	return GetEventParameter( fEvent, inName, typeWildCard, NULL, 0, outSize, NULL ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	Boolean				inValue ) +{ +	return SetParameter<Boolean>( inName, typeBoolean, inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	Boolean*			outValue ) +{ +	return GetParameter<Boolean>( inName, typeBoolean, outValue ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	bool				inValue ) +{ +	return SetParameter<Boolean>( inName, typeBoolean, (Boolean) inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	bool*				outValue ) +{ +	return GetParameter<Boolean>( inName, sizeof( Boolean ), (Boolean*) outValue ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	Point				inPt ) +{ +	return SetParameter<Point>( inName, typeQDPoint, inPt ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	Point*				outPt ) +{ +	return GetParameter<Point>( inName, typeQDPoint, outPt ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	const HIPoint&		inPt ) +{ +	return SetParameter<HIPoint>( inName, typeHIPoint, inPt ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	HIPoint*			outPt ) +{ +	return GetParameter<HIPoint>( inName, typeHIPoint, outPt ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	const Rect&			inRect ) +{ +	return SetParameter<Rect>( inName, typeQDRectangle, inRect ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	Rect*				outRect ) +{ +	return GetParameter<Rect>( inName, typeQDRectangle, outRect ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	const HIRect&		inRect ) +{ +	return SetParameter<HIRect>( inName, typeHIRect, inRect ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	HIRect*				outRect ) +{ +	return GetParameter<HIRect>( inName, typeHIRect, outRect ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	const HISize&		inSize ) +{ +	return SetParameter<HISize>( inName, typeHISize, inSize ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	HISize*				outSize ) +{ +	return GetParameter<HISize>( inName, typeHISize, outSize ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	RgnHandle			inRegion ) +{ +	return SetParameter<RgnHandle>( inName, typeQDRgnHandle, inRegion ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	RgnHandle*			outRegion ) +{ +	return GetParameter<RgnHandle>( inName, typeQDRgnHandle, outRegion ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	WindowRef			inWindow ) +{ +	return SetParameter<WindowRef>( inName, typeWindowRef, inWindow ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	WindowRef*			outWindow ) +{ +	return GetParameter<WindowRef>( inName, typeWindowRef, outWindow ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	ControlRef			inControl ) +{ +	return SetParameter<ControlRef>( inName, typeControlRef, inControl ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	ControlRef* outControl ) +{ +	return GetParameter<ControlRef>( inName, typeControlRef, outControl ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	MenuRef				inMenu ) +{ +	return SetParameter<MenuRef>( inName, typeMenuRef, inMenu ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	MenuRef*			outMenu ) +{ +	return GetParameter<MenuRef>( inName, typeMenuRef, outMenu ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	DragRef				inDrag ) +{ +	return SetParameter<DragRef>( inName, typeDragRef, inDrag ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	DragRef*			outDrag ) +{ +	return GetParameter<DragRef>( inName, typeDragRef, outDrag ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	UInt32				inValue ) +{ +	return SetParameter<UInt32>( inName, typeUInt32, inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	UInt32*				outValue ) +{ +	return GetParameter<UInt32>( inName, typeUInt32, outValue ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName		inName, +	const HICommand&	inValue ) +{ +	return SetParameter<HICommand>( inName, typeHICommand, inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	HICommand*			outValue ) +{ +	return GetParameter<HICommand>( inName, typeHICommand, outValue ); +} + +//----------------------------------------------------------------------------------- +//	SetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::SetParameter( +	EventParamName			inName, +	const ControlPartCode&	inValue ) +{ +	return SetParameter<ControlPartCode>( inName, typeControlPartCode, inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetParameter +//----------------------------------------------------------------------------------- +// +OSStatus TCarbonEvent::GetParameter( +	EventParamName		inName, +	ControlPartCode*	outValue ) +{ +	return GetParameter<ControlPartCode>( inName, typeControlPartCode, outValue ); +} diff --git a/macosx/TCarbonEvent.h b/macosx/TCarbonEvent.h new file mode 100644 index 000000000..d40da9795 --- /dev/null +++ b/macosx/TCarbonEvent.h @@ -0,0 +1,230 @@ +/* +    File:		TCarbonEvent.h +     +    Version:	1.0 + +	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. +				("Apple") in consideration of your agreement to the following terms, and your +				use, installation, modification or redistribution of this Apple software +				constitutes acceptance of these terms.  If you do not agree with these terms, +				please do not use, install, modify or redistribute this Apple software. + +				In consideration of your agreement to abide by the following terms, and subject +				to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs +				copyrights in this original Apple software (the "Apple Software"), to use, +				reproduce, modify and redistribute the Apple Software, with or without +				modifications, in source and/or binary forms; provided that if you redistribute +				the Apple Software in its entirety and without modifications, you must retain +				this notice and the following text and disclaimers in all such redistributions of +				the Apple Software.  Neither the name, trademarks, service marks or logos of +				Apple Computer, Inc. may be used to endorse or promote products derived from the +				Apple Software without specific prior written permission from Apple.  Except as +				expressly stated in this notice, no other rights or licenses, express or implied, +				are granted by Apple herein, including but not limited to any patent rights that +				may be infringed by your derivative works or by other works in which the Apple +				Software may be incorporated. + +				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO +				WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +				WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +				PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +				COMBINATION WITH YOUR PRODUCTS. + +				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +				CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +				GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +				ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +				OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +				(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +				ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +	Copyright © 2002 Apple Computer, Inc., All Rights Reserved +*/ + +#ifndef TCarbonEvent_H_ +#define TCarbonEvent_H_ + +#include <Carbon/Carbon.h> + +class TCarbonEvent +{ +public: +	// Construction/Destruction +	TCarbonEvent( +					UInt32				inClass, +					UInt32				inKind ); +	TCarbonEvent( +					EventRef			inEvent ); +	virtual ~TCarbonEvent(); +	 +	UInt32		GetClass() const; +	UInt32		GetKind() const; +	 +	// Time +	void		SetTime( +					EventTime inTime ); +	EventTime	GetTime() const; +	 +	// Retention +	void		Retain(); +	void		Release(); +	 +	// Accessors +	operator	EventRef&() +					{ return fEvent; }; +	EventRef	GetEventRef() +					{ return fEvent; } +	 +	// Posting +	OSStatus 	PostToQueue( +					EventQueueRef		inQueue, +					EventPriority		inPriority = kEventPriorityStandard ); + +	// Parameters +	OSStatus	SetParameter( +					EventParamName		inName, +					EventParamType		inType, +					UInt32				inSize, +					const void*			inData ); +	OSStatus	GetParameter( +					EventParamName		inName, +					EventParamType		inType, +					UInt32				inBufferSize, +					void*				outData ); + +	OSStatus	GetParameterType( +					EventParamName		inName, +					EventParamType*		outType ); +	OSStatus	GetParameterSize( +					EventParamName		inName, +					UInt32*				outSize ); + +	// Simple parameters +	OSStatus	SetParameter( +					EventParamName		inName, +					Boolean				inValue ); +	OSStatus	GetParameter( +					EventParamName		inName, +					Boolean*			outValue ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					bool				inValue ); +	OSStatus	GetParameter( +					EventParamName		inName, +					bool*				outValue ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					Point				inPt ); +	OSStatus	GetParameter( +					EventParamName		inName, +					Point*				outPt ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					const HIPoint&		inPt ); + +	OSStatus	GetParameter( +					EventParamName		inName, +					HIPoint*			outPt ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					const Rect&			inRect ); +	OSStatus	GetParameter( +					EventParamName		inName, +					Rect*				outRect ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					const HIRect&		inRect ); +	OSStatus	GetParameter( +					EventParamName		inName, +					HIRect*				outRect ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					const HISize&		inSize ); +	OSStatus	GetParameter( +					EventParamName		inName, +					HISize*				outSize ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					RgnHandle			inRegion ); +	OSStatus	GetParameter( +					EventParamName		inName, +					RgnHandle*			outRegion ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					WindowRef			inWindow ); +	OSStatus	GetParameter( +					EventParamName		inName, +					WindowRef*			outWindow ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					ControlRef			inControl ); +	OSStatus	GetParameter( +					EventParamName		inName, +					ControlRef* outControl ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					MenuRef				inMenu ); +	OSStatus	GetParameter( +					EventParamName		inName, +					MenuRef*			outMenu ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					DragRef				inDrag ); +	OSStatus	GetParameter( +					EventParamName		inName, +					DragRef*			outDrag ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					UInt32				inValue ); +	OSStatus	GetParameter( +					EventParamName		inName, +					UInt32*				outValue ); +	 +	OSStatus	SetParameter( +					EventParamName		inName, +					const HICommand&	inValue ); +	OSStatus	GetParameter( +					EventParamName		inName, +					HICommand*			outValue ); + +	OSStatus	SetParameter( +					EventParamName		inName, +					const ControlPartCode&	inValue ); +	OSStatus	GetParameter( +					EventParamName		inName, +					ControlPartCode*			outValue ); + +	// Template parameters +	template <class T> OSStatus SetParameter( +		EventParamName	inName, +		EventParamType	inType, +		const T&		inValue ) +	{ +		return SetParameter( inName, inType, sizeof( T ), &inValue ); +	} +			 +	template <class T> OSStatus GetParameter( +		EventParamName	inName, +		EventParamType	inType, +		T*				outValue ) +	{ +		return GetParameter( inName, inType, sizeof( T ), outValue ); +	} +	 +private: +	EventRef	fEvent; +}; + +#endif // TCarbonEvent_H_ diff --git a/macosx/TRect.h b/macosx/TRect.h new file mode 100644 index 000000000..5a4199300 --- /dev/null +++ b/macosx/TRect.h @@ -0,0 +1,496 @@ +/* +    File:		TRect.h +     +    Version:	1.0 + +	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. +				("Apple") in consideration of your agreement to the following terms, and your +				use, installation, modification or redistribution of this Apple software +				constitutes acceptance of these terms.  If you do not agree with these terms, +				please do not use, install, modify or redistribute this Apple software. + +				In consideration of your agreement to abide by the following terms, and subject +				to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs +				copyrights in this original Apple software (the "Apple Software"), to use, +				reproduce, modify and redistribute the Apple Software, with or without +				modifications, in source and/or binary forms; provided that if you redistribute +				the Apple Software in its entirety and without modifications, you must retain +				this notice and the following text and disclaimers in all such redistributions of +				the Apple Software.  Neither the name, trademarks, service marks or logos of +				Apple Computer, Inc. may be used to endorse or promote products derived from the +				Apple Software without specific prior written permission from Apple.  Except as +				expressly stated in this notice, no other rights or licenses, express or implied, +				are granted by Apple herein, including but not limited to any patent rights that +				may be infringed by your derivative works or by other works in which the Apple +				Software may be incorporated. + +				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO +				WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +				WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +				PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +				COMBINATION WITH YOUR PRODUCTS. + +				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +				CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +				GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +				ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +				OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +				(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +				ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +	Copyright © 2002 Apple Computer, Inc., All Rights Reserved +*/ + +#ifndef TRect_H_ +#define TRect_H_ + +#include <Carbon/Carbon.h> + +class TRect +	: public HIRect +{ +public: +	// Construction/Destruction +	TRect(); +	TRect( +						const HIRect*		inRect ); +	TRect( +						const HIRect&		inRect ); +	TRect( +						const HIPoint&		inOrigin, +						const HISize&		inSize ); +	TRect( +						float				inX, +						float				inY, +						float				inWidth, +						float				inHeight ); +	TRect( +						const Rect&			inRect ); +	~TRect(); +	 +	// Operators +	operator		HIRect*() +						{ return this; } +	operator		Rect() const; + +	// Accessors +	float			MinX() const +						{ return CGRectGetMinX( *this ); } +	float			MaxX() const +						{ return CGRectGetMaxX( *this ); } +	float			MinY() const +						{ return CGRectGetMinY( *this ); } +	float			MaxY() const +						{ return CGRectGetMaxY( *this ); } + +	float			Width() const +						{ return CGRectGetWidth( *this ); } +	float			Height() const +						{ return CGRectGetHeight( *this ); } +	 +	const HIPoint&	Origin() const +						{ return origin; } +	const HISize&	Size() const +						{ return size; } + +	float			CenterX() const +						{ return CGRectGetMidX( *this ); } +	float			CenterY() const +						{ return CGRectGetMidY( *this ); } +	HIPoint			Center() const; +	 +	// Modifiers +	const HIRect&	Inset( +						float				inX, +						float				inY ); +	const HIRect&	Outset( +						float				inX, +						float				inY ); +	const HIRect&	MoveBy( +						float				inDx, +						float				inDy ); +	const HIRect&	MoveTo( +						float				inX, +						float				inY ); + +	const HIRect&	Set( +						const HIRect*		inRect ); +	const HIRect&	Set( +						const HIRect&		inRect ); +	const HIRect&	Set(				 +						float				inX, +						float				inY, +						float				inWidth, +						float				inHeight ); +	const HIRect&	Set( +						const Rect*			inRect ); + +	const HIRect&	SetAroundCenter(				 +						float				inCenterX, +						float				inCenterY, +						float				inWidth, +						float				inHeight ); + +	const HIRect&	SetWidth( +						float				inWidth ); +	const HIRect&	SetHeight( +						float				inHeight ); + +	const HIRect&	SetOrigin( +						const HIPoint&		inOrigin ); +	const HIRect&	SetOrigin( +						float				inX, +						float				inY ); +	const HIRect&	SetSize( +						const HISize&		inSize ); +	const HIRect&	SetSize( +						float				inWidth, +						float				inHeight ); + +	// Tests +	bool			Contains( +						const HIPoint&		inPoint ); +	bool			Contains( +						const HIRect&		inRect ); +	bool			Contains( +						const Point&		inPoint ); +	bool			Contains( +						const Rect&			inRect ); +}; + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect() +{ +} + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect( +	const HIRect*		inRect ) +{ +	*this = *inRect; +} + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect( +	const HIRect&		inRect ) +{ +	origin = inRect.origin; +	size = inRect.size; +} + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect( +	const HIPoint&		inOrigin, +	const HISize&		inSize ) +{ +	origin = inOrigin; +	size = inSize; +} + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect( +	float				inX, +	float				inY, +	float				inWidth, +	float				inHeight ) +{ +	*this = CGRectMake( inX, inY, inWidth, inHeight ); +} + +//----------------------------------------------------------------------------------- +//	TRect destructor +//----------------------------------------------------------------------------------- +// +inline TRect::~TRect() +{ +} + +//----------------------------------------------------------------------------------- +//	TRect constructor +//----------------------------------------------------------------------------------- +// +inline TRect::TRect( +	const Rect&		inRect ) +{ +	Set( &inRect ); +} + +//----------------------------------------------------------------------------------- +//	Rect operator +//----------------------------------------------------------------------------------- +//	Converts the HIRect to a QD rect and returns it +// +inline TRect::operator Rect() const +{ +	Rect	qdRect; +	 +	qdRect.top = (SInt16) MinY(); +	qdRect.left = (SInt16) MinX(); +	qdRect.bottom = (SInt16) MaxY(); +	qdRect.right = (SInt16) MaxX(); + +	return qdRect; +} + +//----------------------------------------------------------------------------------- +//	Center +//----------------------------------------------------------------------------------- +// +inline HIPoint TRect::Center() const +{ +	return CGPointMake( CGRectGetMidX( *this ), CGRectGetMidY( *this ) ); +} + +//----------------------------------------------------------------------------------- +//	Inset +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Inset( +	float				inX, +	float				inY ) +{ +	*this = CGRectInset( *this, inX, inY ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Outset +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Outset( +	float				inX, +	float				inY ) +{ +	*this = CGRectInset( *this, -inX, -inY ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	MoveBy +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::MoveBy( +	float				inDx, +	float				inDy ) +{ +	origin = CGPointMake( MinX() + inDx, MinY() + inDy ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	MoveTo +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::MoveTo( +	float				inX, +	float				inY ) +{ +	origin = CGPointMake( inX, inY ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Set +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Set( +	const HIRect*		inRect ) +{ +	*this = *inRect; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Set +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Set( +	const HIRect&			inRect ) +{ +	*this = inRect; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Set +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Set( +	float				inX, +	float				inY, +	float				inWidth, +	float				inHeight ) +{ +	*this = CGRectMake( inX, inY, inWidth, inHeight ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Set +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::Set( +	const Rect*			inRect ) +{ +	origin.x = inRect->left; +	origin.y = inRect->top; +	size.width = inRect->right - inRect->left; +	size.height = inRect->bottom - inRect->top; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetAroundCenter +//----------------------------------------------------------------------------------- +//	Sets the rectangle by specifying dimensions around a center point +// +inline const HIRect& TRect::SetAroundCenter( +	float				inCenterX, +	float				inCenterY, +	float				inWidth, +	float				inHeight ) +{ +	*this = CGRectMake( inCenterX - inWidth/2, inCenterY - inHeight/2, inWidth, inHeight ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetWidth +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetWidth( +	float				inWidth ) +{ +	size.width = inWidth; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetHeight +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetHeight( +	float				inHeight ) +{ +	size.height = inHeight; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetOrigin +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetOrigin( +	const HIPoint&		inOrigin ) +{ +	origin = inOrigin; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetOrigin +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetOrigin( +	float				inX, +	float				inY ) +{ +	origin = CGPointMake( inX, inY ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetSize +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetSize( +	const HISize&		inSize ) +{ +	size = inSize; +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	SetSize +//----------------------------------------------------------------------------------- +// +inline const HIRect& TRect::SetSize( +	float				inWidth, +	float				inHeight ) +{ +	size = CGSizeMake( inWidth, inHeight ); +	 +	return *this; +} + +//----------------------------------------------------------------------------------- +//	Contains +//----------------------------------------------------------------------------------- +// +inline bool TRect::Contains( +	const HIPoint&		inPoint ) +{ +	return CGRectContainsPoint( *this, inPoint ); +} + +//----------------------------------------------------------------------------------- +//	Contains +//----------------------------------------------------------------------------------- +// +inline bool TRect::Contains( +	const HIRect&		inRect ) +{ +	return CGRectContainsRect( *this, inRect ); +} + +//----------------------------------------------------------------------------------- +//	Contains +//----------------------------------------------------------------------------------- +// +inline bool TRect::Contains( +	const Point&		inPoint ) +{ +	return Contains( CGPointMake( inPoint.h, inPoint.v ) ); +} + +//----------------------------------------------------------------------------------- +//	Contains +//----------------------------------------------------------------------------------- +// +inline bool TRect::Contains( +	const Rect&		inRect ) +{ +	return Contains( CGRectMake( inRect.left, inRect.top, +			inRect.right - inRect.left, inRect.bottom - inRect.top ) ); +} + +#endif // TRect_H_ diff --git a/macosx/TView.cxx b/macosx/TView.cxx new file mode 100644 index 000000000..9ed02b110 --- /dev/null +++ b/macosx/TView.cxx @@ -0,0 +1,1462 @@ +/* +    File:		TView.cp +     +    Version:	1.0 + +	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. +				("Apple") in consideration of your agreement to the following terms, and your +				use, installation, modification or redistribution of this Apple software +				constitutes acceptance of these terms.  If you do not agree with these terms, +				please do not use, install, modify or redistribute this Apple software. + +				In consideration of your agreement to abide by the following terms, and subject +				to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs +				copyrights in this original Apple software (the "Apple Software"), to use, +				reproduce, modify and redistribute the Apple Software, with or without +				modifications, in source and/or binary forms; provided that if you redistribute +				the Apple Software in its entirety and without modifications, you must retain +				this notice and the following text and disclaimers in all such redistributions of +				the Apple Software.  Neither the name, trademarks, service marks or logos of +				Apple Computer, Inc. may be used to endorse or promote products derived from the +				Apple Software without specific prior written permission from Apple.  Except as +				expressly stated in this notice, no other rights or licenses, express or implied, +				are granted by Apple herein, including but not limited to any patent rights that +				may be infringed by your derivative works or by other works in which the Apple +				Software may be incorporated. + +				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO +				WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +				WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +				PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +				COMBINATION WITH YOUR PRODUCTS. + +				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +				CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +				GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +				ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +				OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +				(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +				ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +	Copyright © 2002 Apple Computer, Inc., All Rights Reserved +*/ + +/* + NOTE: This is NOWHERE near a completely exhaustive implementation of a view. There are +       many more carbon events one could intercept and hook into this. +*/ + +#include "TView.h" + +//----------------------------------------------------------------------------------- +//	constants +//----------------------------------------------------------------------------------- +// +const EventTypeSpec kHIObjectEvents[] = +{	{ kEventClassHIObject, kEventHIObjectConstruct }, +	{ kEventClassHIObject, kEventHIObjectInitialize }, +	{ kEventClassHIObject, kEventHIObjectDestruct } +}; +	 +const EventTypeSpec kHIViewEvents[] = +{	{ kEventClassCommand, kEventCommandProcess }, +	{ kEventClassCommand, kEventCommandUpdateStatus }, +	 +	{ kEventClassControl, kEventControlInitialize }, +	{ kEventClassControl, kEventControlDraw }, +	{ kEventClassControl, kEventControlHitTest }, +	{ kEventClassControl, kEventControlGetPartRegion }, +	{ kEventClassControl, kEventControlGetData }, +	{ kEventClassControl, kEventControlSetData }, +	{ kEventClassControl, kEventControlGetOptimalBounds }, +	{ kEventClassControl, kEventControlBoundsChanged }, +	{ kEventClassControl, kEventControlTrack }, +	{ kEventClassControl, kEventControlGetSizeConstraints }, +	{ kEventClassControl, kEventControlHit }, +	 +	{ kEventClassControl, kEventControlHiliteChanged }, +	{ kEventClassControl, kEventControlActivate }, +	{ kEventClassControl, kEventControlDeactivate }, +	{ kEventClassControl, kEventControlValueFieldChanged }, +	{ kEventClassControl, kEventControlTitleChanged }, +	{ kEventClassControl, kEventControlEnabledStateChanged }, +}; + +// This param name was accidentally left unexported for +// the release of Jaguar. +const EventParamName kEventParamControlLikesDrag = 'cldg'; + +//----------------------------------------------------------------------------------- +//	TView constructor +//----------------------------------------------------------------------------------- +// +TView::TView( +	HIViewRef			inControl ) +	:	fViewRef( inControl ) +{ +	verify_noerr( InstallEventHandler( GetControlEventTarget( fViewRef ), ViewEventHandler, +			GetEventTypeCount( kHIViewEvents ), kHIViewEvents, this, &fHandler ) ); + +	mouseEventHandler = NULL; +	fAutoInvalidateFlags = 0; +	debugPrint = false; +} + +//----------------------------------------------------------------------------------- +//	TView destructor +//----------------------------------------------------------------------------------- +// +TView::~TView() +{ +	// If we have installed our custom mouse events handler on the window, +	// go forth and remove it. Note: -1 is used to indicate that no handler has +	// been installed yet, but we want to once we get a window. +	if ( mouseEventHandler != NULL && mouseEventHandler != reinterpret_cast<void*>( -1 ) ) +		{ +		OSStatus err; +		err = RemoveEventHandler( mouseEventHandler ); +		assert( err == noErr ); +		} +	mouseEventHandler = NULL; +} + +//----------------------------------------------------------------------------------- +//	Initialize +//----------------------------------------------------------------------------------- +//	Called during HIObject construction, this is your subclasses' chance to extract +//	any parameters it might have added to the initialization event passed into the +//	HIObjectCreate call. +// +OSStatus TView::Initialize( TCarbonEvent& /*inEvent*/ ) +{ +	return noErr; +} + +//----------------------------------------------------------------------------------- +//	GetBehaviors +//----------------------------------------------------------------------------------- +//	Returns our behaviors. Any subclass that overrides this should OR in its behaviors +//	into the inherited behaviors. +// +UInt32 TView::GetBehaviors() +{ +	return kControlSupportsDataAccess | kControlSupportsGetRegion; +} + +//----------------------------------------------------------------------------------- +//	Draw +//----------------------------------------------------------------------------------- +//	Draw your view. You should draw based on VIEW coordinates, not frame coordinates. +// +void TView::Draw( +	RgnHandle			/*inLimitRgn*/, +	CGContextRef		/*inContext*/ ) +{ +} + +//----------------------------------------------------------------------------------- +//	HitTest +//----------------------------------------------------------------------------------- +//	Asks your view to return what part of itself (if any) is hit by the point given +//	to it. The point is in VIEW coordinates, so you should get the view rect to do +//	bounds checking. +// +ControlPartCode TView::HitTest( +	const HIPoint&		/*inWhere*/ ) +{ +	return kControlNoPart; +} + +//----------------------------------------------------------------------------------- +//	GetRegion +//----------------------------------------------------------------------------------- +//	This is called when someone wants to know certain metrics regarding this view. +//	The base class does nothing. Subclasses should handle their own parts, such as +//	the content region by overriding this method. The structure region is, by default, +//	the view's bounds. If a subclass does not have a region for a given part, it  +//	should always call the inherited method. +// +OSStatus TView::GetRegion( +	ControlPartCode		inPart, +	RgnHandle			outRgn ) +{ +#pragma unused( inPart, outRgn ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	PrintDebugInfo +//----------------------------------------------------------------------------------- +//	This is called when asked to print debugging information. +// +void TView::PrintDebugInfo() +{ +} + +//----------------------------------------------------------------------------------- +//	GetData +//----------------------------------------------------------------------------------- +//	Gets some data from our view. Subclasses should override to handle their own +//	defined data tags. If a tag is not understood by the subclass, it should call the +//	inherited method. As a convienience, we map the request for ControlKind into our +//	GetKind method. +// +OSStatus TView::GetData( +	OSType				inTag, +	ControlPartCode		inPart, +	Size				inSize, +	Size*				outSize, +	void*				inPtr ) +{ +#pragma unused( inPart ) + +	OSStatus			err = noErr; +	 +	switch( inTag ) +	{ +		case kControlKindTag: +			if ( inPtr ) +			{ +				if ( inSize != sizeof( ControlKind ) ) +					err = errDataSizeMismatch; +				else +					( *(ControlKind *) inPtr ) = GetKind(); +			} +			*outSize = sizeof( ControlKind ); +			break; +		 +		default: +			err = eventNotHandledErr; +			break; +	} +	 +	return err; +} + +//----------------------------------------------------------------------------------- +//	SetData +//----------------------------------------------------------------------------------- +//	Sets some data on our control. Subclasses should override to handle their own +//	defined data tags. If a tag is not understood by the subclass, it should call the +//	inherited method. +// +OSStatus TView::SetData( +	OSType				inTag, +	ControlPartCode		inPart, +	Size				inSize, +	const void*			inPtr ) +{ +#pragma unused( inTag, inPart, inSize, inPtr ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	GetOptimalSize +//----------------------------------------------------------------------------------- +//	Someone wants to know this view's optimal size and text baseline, probably to help +//	do some type of layout. The base class does nothing, but subclasses should +//	override and do something meaningful here. +// +OSStatus TView::GetOptimalSize( +	HISize*				outSize, +	float*				outBaseLine ) +{ +#pragma unused( outSize, outBaseLine ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	GetSizeConstraints +//----------------------------------------------------------------------------------- +//	Someone wants to know this view's minimum and maximum sizes, probably to help +//	do some type of layout. The base class does nothing, but subclasses should +//	override and do something meaningful here. +// +OSStatus TView::GetSizeConstraints( +	HISize*				outMin, +	HISize*				outMax ) +{ +#pragma unused( outMin, outMax ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	BoundsChanged +//----------------------------------------------------------------------------------- +//	The bounds of our view have changed. Subclasses can override here to make note +//	of it and flush caches, etc. The base class does nothing. +// +OSStatus TView::BoundsChanged( +	UInt32 				inOptions, +	const HIRect& 		inOriginalBounds, +	const HIRect& 		inCurrentBounds, +	RgnHandle 			inInvalRgn ) +{ +#pragma unused( inOptions, inOriginalBounds, inCurrentBounds, inInvalRgn ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	ControlHit +//----------------------------------------------------------------------------------- +//	The was hit.  Subclasses can overide to care about what part was hit. +// +OSStatus TView::ControlHit( +	ControlPartCode		inPart, +	UInt32				inModifiers ) +{ +#pragma unused( inPart, inModifiers ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	HiliteChanged +//----------------------------------------------------------------------------------- +//	The hilite of our view has changed. Subclasses can override here to make note +//	of it and flush caches, etc. The base class does nothing. +// +OSStatus TView::HiliteChanged( +	ControlPartCode		inOriginalPart, +	ControlPartCode		inCurrentPart, +	RgnHandle 			inInvalRgn ) +{ +#pragma unused( inOriginalPart, inCurrentPart, inInvalRgn ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	DragEnter +//----------------------------------------------------------------------------------- +//	A drag has entered our bounds. The Drag and Drop interface also should have been +//	activated or else this method will NOT be called. If true is returned, this view +//	likes the drag and will receive drag within/leave/receive messages as appropriate. +//	If false is returned, it is assumed the drag is not valid for this view, and no +//	further drag activity will flow into this view unless the drag leaves and is +//	re-entered. +// +bool TView::DragEnter( +	DragRef				inDrag ) +{ +#pragma unused( inDrag ) + +	return false; +} + +//----------------------------------------------------------------------------------- +//	DragWithin +//----------------------------------------------------------------------------------- +//	A drag has moved within our bounds. In order for this method to be called, the +//	view must have signaled the drag as being desirable in the DragEnter method. The +//	Drag and Drop interface also should have been activated. +// +bool TView::DragWithin( +	DragRef				inDrag ) +{ +#pragma unused( inDrag ) + +	return false; +} + +//----------------------------------------------------------------------------------- +//	DragLeave +//----------------------------------------------------------------------------------- +//	A drag has left. Deal with it. Subclasses should override as necessary. The +//	Drag and Drop interface should be activated in order for this method to be valid. +//	The drag must have also been accepted in the DragEnter method, else this method +//	will NOT be called. +// +bool TView::DragLeave( +	DragRef				inDrag ) +{ +#pragma unused( inDrag ) + +	return false; +} + +//----------------------------------------------------------------------------------- +//	DragReceive +//----------------------------------------------------------------------------------- +//	Deal with receiving a drag. By default we return dragNotAcceptedErr. I'm not sure +//	if this is correct, or eventNotHandledErr. Time will tell... +// +OSStatus TView::DragReceive( +	DragRef				inDrag ) +{ +#pragma unused( inDrag ) + +	return dragNotAcceptedErr; +} + +//----------------------------------------------------------------------------------- +//	Track +//----------------------------------------------------------------------------------- +//	Default tracking method. Subclasses should override as necessary. We do nothing +//	here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::Track( +	TCarbonEvent&		inEvent, +	ControlPartCode*	outPart ) +{ +#pragma unused( inEvent, outPart ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	SetFocusPart +//----------------------------------------------------------------------------------- +//	Handle focusing. Our base behavior is to punt. +// +OSStatus TView::SetFocusPart( +	ControlPartCode		inDesiredFocus, +	RgnHandle			inInvalidRgn, +	Boolean				inFocusEverything, +	ControlPartCode*	outActualFocus ) +{ +#pragma unused( inDesiredFocus, inInvalidRgn, inFocusEverything, outActualFocus ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	ProcessCommand +//----------------------------------------------------------------------------------- +//	Process a command. Subclasses should override as necessary. +// +OSStatus TView::ProcessCommand( +	const HICommand&	inCommand ) +{ +#pragma unused( inCommand ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	UpdateCommandStatus +//----------------------------------------------------------------------------------- +//	Update the status for a command. Subclasses should override as necessary. +// +OSStatus +TView::UpdateCommandStatus( +	const HICommand&	inCommand ) +{ +#pragma unused( inCommand ) + +	return eventNotHandledErr; +} + +OSStatus TView::MouseDown(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ , +			  TCarbonEvent& /*inEvent*/) +{ +	return eventNotHandledErr; +} + +OSStatus TView::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ) +{ +	return eventNotHandledErr; +} + +OSStatus TView::MouseDragged(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ) +{ +	return eventNotHandledErr; +} + +OSStatus TView::MouseEntered(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ) +{ +	return eventNotHandledErr; +} + +OSStatus TView::MouseExited(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ) +{ +	return eventNotHandledErr; +} + +OSStatus TView::MouseWheelMoved( EventMouseWheelAxis /*inAxis*/, SInt32 /*inDelta*/, UInt32 /*inKeyModifiers*/ ) +{ +	return eventNotHandledErr; +} + +OSStatus TView::ContextualMenuClick( HIPoint& /*inMouseLocation*/ ) +{ +	return eventNotHandledErr; +} + + +//----------------------------------------------------------------------------------- +//	ActivateInterface +//----------------------------------------------------------------------------------- +//	This routine is used to allow a subclass to turn on a specific event or suite of +//	events, like Drag and Drop. This allows us to keep event traffic down if we are +//	not interested, but register for the events if we are. +// +OSStatus TView::ActivateInterface( +	TView::Interface	inInterface ) +{ +	OSStatus		result = noErr; +	 +	switch( inInterface ) +	{ +		case kDragAndDrop: +			{ +				static const EventTypeSpec kDragEvents[] = +				{ +					{ kEventClassControl, kEventControlDragEnter },			 +					{ kEventClassControl, kEventControlDragLeave },			 +					{ kEventClassControl, kEventControlDragWithin },			 +					{ kEventClassControl, kEventControlDragReceive } +				}; +				 +				result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kDragEvents ), +						kDragEvents ); + +				SetControlDragTrackingEnabled( GetViewRef(), true); +			} +			break; + +		case kKeyboardFocus: +			{ +				static const EventTypeSpec kKeyboardFocusEvents[] = +				{ +					{ kEventClassControl, kEventControlSetFocusPart }, +					{ kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, +				}; +				 +				result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kKeyboardFocusEvents ), +						kKeyboardFocusEvents ); +			} +			break; + +		case kMouse: +			{ +				if ( mouseEventHandler == NULL ) +					{ +					// This case is quite different: Mouse events are delivered to the window, not the controls. +					// mouse wheel events are the exception: They ARE delivered to the control +					static const EventTypeSpec kControlMouseEvents[] = +					{ +						{ kEventClassMouse, kEventMouseWheelMoved }, +						{ kEventClassControl, kEventControlContextualMenuClick }, +						// So we can reinstall our events when the window changes +						{ kEventClassControl, kEventControlOwningWindowChanged },  +					}; + +					result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kControlMouseEvents ), +									  kControlMouseEvents ); +					assert( result == noErr ); +					} + +				if ( this->GetOwner() != NULL ) +					{ +					// We use "-1" to indicate that we want to install an event handler once we get a window +					if ( mouseEventHandler != NULL &&  mouseEventHandler != reinterpret_cast<void*>( -1 ) ) +						{ +						result = RemoveEventHandler( mouseEventHandler ); +						assert( result != NULL ); +						} +					mouseEventHandler = NULL; +					 +					static const EventTypeSpec kWindowMouseEvents[] = +					{ +						{ kEventClassMouse, kEventMouseDown }, +						{ kEventClassMouse, kEventMouseUp }, +						{ kEventClassMouse, kEventMouseMoved }, +						{ kEventClassMouse, kEventMouseDragged }, +					}; + +					assert( mouseEventHandler == NULL ); +					result = InstallEventHandler( GetWindowEventTarget( this->GetOwner() ), WindowEventHandler, +								      GetEventTypeCount( kWindowMouseEvents ), kWindowMouseEvents,  +								      this, &mouseEventHandler ); +					assert( result == noErr && mouseEventHandler != NULL ); +					} +				// If we have no window yet. Set the mouseEventHandler to -1 so when we get one we +				// will install the event handler +				else +					{ +					mouseEventHandler = reinterpret_cast<EventHandlerRef>( -1 ); +					} +			} +			break; +		case kMouseTracking: +		  { +		    { +		      static const EventTypeSpec kControlMouseEvents[] = +			{ +			  { kEventClassMouse, kEventMouseEntered }, // only works if mousetracking is started +			  { kEventClassMouse, kEventMouseExited }, // only works if mousetracking is started +			}; +		       +		      result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kControlMouseEvents ), +						       kControlMouseEvents ); +		      assert( result == noErr ); +		    } +		  } + +		//default: +		//	assert( false ); +	} +	 +	return result; +} + +OSStatus TView::InstallTimer( EventTimerInterval inFireDelay, EventLoopTimerRef* outTimer ) +{ +	return InstallEventLoopTimer( GetCurrentEventLoop(), inFireDelay, inFireDelay, TimerEventHandler, this, outTimer ); +} + +//----------------------------------------------------------------------------------- +//	RegisterSubclass +//----------------------------------------------------------------------------------- +//	This routine should be called by subclasses so they can be created as HIObjects. +// +OSStatus TView::RegisterSubclass( +	CFStringRef			inID, +	ConstructProc		inProc ) +{ +	return HIObjectRegisterSubclass( inID, kHIViewClassID, 0, ObjectEventHandler, +			GetEventTypeCount( kHIObjectEvents ), kHIObjectEvents, (void*) inProc, NULL ); +} + +//----------------------------------------------------------------------------------- +//	ObjectEventHandler +//----------------------------------------------------------------------------------- +//	Our static event handler proc. We handle any HIObject based events directly in +// 	here at present. +// +pascal OSStatus TView::ObjectEventHandler( +	EventHandlerCallRef	inCallRef, +	EventRef			inEvent, +	void*				inUserData ) +{ +	OSStatus			result = eventNotHandledErr; +	TView*				view = (TView*) inUserData; +	TCarbonEvent		event( inEvent ); +	 +	switch ( event.GetClass() ) +	{ +		case kEventClassHIObject: +			switch ( event.GetKind() ) +			{ +				case kEventHIObjectConstruct: +					{ +						ControlRef		control; // ControlRefs are HIObjectRefs +						TView*			view; + +						result = event.GetParameter<HIObjectRef>( kEventParamHIObjectInstance, +								typeHIObjectRef, (HIObjectRef*)&control ); +						require_noerr( result, ParameterMissing ); +						 +						// on entry for our construct event, we're passed the +						// creation proc we registered with for this class. +						// we use it now to create the instance, and then we +						// replace the instance parameter data with said instance +						// as type void. + +						result = (*(ConstructProc)inUserData)( control, &view ); +						if ( result == noErr ) +							event.SetParameter<TViewPtr>( kEventParamHIObjectInstance, +									typeVoidPtr, view );  +					} +					break; +				 +				case kEventHIObjectInitialize: +					result = CallNextEventHandler( inCallRef, inEvent ); +					if ( result == noErr ) +						result = view->Initialize( event ); +					break; +				 +				case kEventHIObjectDestruct: +					delete view; +					break; +			} +			break; +	} + +ParameterMissing: + +	return result; +} + +//----------------------------------------------------------------------------------- +//	ViewEventHandler +//----------------------------------------------------------------------------------- +//	Our static event handler proc. We handle all non-HIObject events here. +// +pascal OSStatus TView::ViewEventHandler( +	EventHandlerCallRef	inCallRef, +	EventRef			inEvent, +	void*				inUserData ) +{ +	OSStatus			result; +	TView*				view = (TView*) inUserData; +	TCarbonEvent		event( inEvent ); +	if (view->debugPrint) +	  fprintf(stderr,"TView::ViewEventHandler\n"); +	result = view->HandleEvent( inCallRef, event ); + +	return result; +} + + +pascal OSStatus TView::WindowEventHandler( +	EventHandlerCallRef	inCallRef, +	EventRef			inEvent, +	void*				inUserData ) +{ +	TView* view = reinterpret_cast<TView*>( inUserData ); +	TCarbonEvent event( inEvent ); + +	const WindowRef window = view->GetOwner(); +	assert( window != NULL ); + +	// If the window is not active, let the standard window handler execute. +	if ( ! IsWindowActive( window ) ) return eventNotHandledErr; +	if (view->debugPrint) +	  fprintf(stderr,"TView::WindowEventHandler\n"); +	 +	const HIViewRef rootView = HIViewGetRoot( window ); +	assert( rootView != NULL ); + +	// TODO: On OS X 10.3, test if this bug still exists +	// This is a hack to work around a bug in the OS. See: +	// http://lists.apple.com/archives/carbon-development/2002/Sep/29/keventmousemovedeventsno.004.txt +	OSStatus err; +	if ( event.GetKind() == kEventMouseMoved ) +	{ +		// We need to set some parameters correctly +		event.SetParameter( kEventParamWindowRef, window ); + +		HIPoint ptMouse; +		event.GetParameter( kEventParamMouseLocation, &ptMouse ); + +		// convert screen coords to window relative +		Rect bounds; +		err = GetWindowBounds( window, kWindowStructureRgn, &bounds ); +		assert( err == noErr ); + +		ptMouse.x -= bounds.left; +		ptMouse.y -= bounds.top; + +		event.SetParameter( kEventParamWindowMouseLocation, ptMouse ); +	} +	 +	HIViewRef targetView = NULL; +	err = HIViewGetViewForMouseEvent( rootView, inEvent, &targetView ); +	assert( err == noErr && targetView != NULL ); +	if (view->debugPrint) +	  fprintf(stderr,"TView::WindowEventHandler root[%08X] viewRef[%08X] targetView[%08X]\n", rootView, view->GetViewRef(), targetView); +	if ( targetView == view->GetViewRef() || event.GetKind() == kEventMouseDragged ) +		{ +		return view->HandleEvent( inCallRef, event ); +		} + +	return eventNotHandledErr; +} + +pascal void TView::TimerEventHandler( EventLoopTimerRef inTimer, void* view ) +{ +	reinterpret_cast<TView*>( view )->TimerFired( inTimer ); +} + +//----------------------------------------------------------------------------------- +//	HandleEvent +//----------------------------------------------------------------------------------- +//	Our object's virtual event handler method. I'm not sure if we need this these days. +//	We used to do various things with it, but those days are long gone... +// +OSStatus TView::HandleEvent( +	EventHandlerCallRef	inCallRef, +	TCarbonEvent&		inEvent ) +{ +#pragma unused( inCallRef ) + +	OSStatus			result = eventNotHandledErr; +	HIPoint				where; +	OSType				tag; +	void *				ptr; +	Size				size, outSize; +	UInt32				features; +	RgnHandle			region = NULL; +	ControlPartCode		part; +	RgnHandle			invalRgn; +	 +	switch ( inEvent.GetClass() ) +	{ +		case kEventClassCommand: +			{ +				HICommand		command; +				 +				result = inEvent.GetParameter( kEventParamDirectObject, &command ); +				require_noerr( result, MissingParameter ); +				 +				switch ( inEvent.GetKind() ) +				{ +					case kEventCommandProcess: +						result = ProcessCommand( command ); +						break; +					 +					case kEventCommandUpdateStatus: +						result = UpdateCommandStatus( command ); +						break; +				} +			} +			break; + +		case kEventClassControl: +			switch ( inEvent.GetKind() ) +			{ +				case kEventControlInitialize: +					features = GetBehaviors(); +					inEvent.SetParameter( kEventParamControlFeatures, features ); +					result = noErr; +					break; +					 +				case kEventControlDraw: +					{ +						CGContextRef		context = NULL; +						 +						inEvent.GetParameter( kEventParamRgnHandle, ®ion ); +						inEvent.GetParameter<CGContextRef>( kEventParamCGContextRef, typeCGContextRef, &context ); + +						Draw( region, context ); +						result = noErr; +					} +					break; + +				case kEventControlHitTest: +					inEvent.GetParameter<HIPoint>( kEventParamMouseLocation, typeHIPoint, &where ); +					part = HitTest( where ); +					inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, part ); +					result = noErr; +					break; +					 +				case kEventControlGetPartRegion: +					inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part ); +					inEvent.GetParameter( kEventParamControlRegion, ®ion ); +					result = GetRegion( part, region ); +					break; +				 +				case kEventControlGetData: +					inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part ); +					inEvent.GetParameter<OSType>( kEventParamControlDataTag, typeEnumeration, &tag ); +					inEvent.GetParameter<Ptr>( kEventParamControlDataBuffer, typePtr, (Ptr*)&ptr ); +					inEvent.GetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, &size ); + +					result = GetData( tag, part, size, &outSize, ptr ); + +					if ( result == noErr ) +						verify_noerr( inEvent.SetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, outSize ) ); +					break; +				 +				case kEventControlSetData: +					inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part ); +					inEvent.GetParameter<OSType>( kEventParamControlDataTag, typeEnumeration, &tag ); +					inEvent.GetParameter<Ptr>( kEventParamControlDataBuffer, typePtr, (Ptr*)&ptr ); +					inEvent.GetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, &size ); + +					result = SetData( tag, part, size, ptr ); +					break; +				 +				case kEventControlGetOptimalBounds: +					{ +						HISize		size; +						float		floatBaseLine; +						 +						result = GetOptimalSize( &size, &floatBaseLine ); +						if ( result == noErr ) +						{ +							Rect		bounds; +							SInt16		baseLine; + +							GetControlBounds( GetViewRef(), &bounds ); + +							bounds.bottom = bounds.top + (SInt16)size.height; +							bounds.right = bounds.left + (SInt16)size.width; +							baseLine = (SInt16)floatBaseLine; +							 +							inEvent.SetParameter( kEventParamControlOptimalBounds, bounds ); +							inEvent.SetParameter<SInt16>( kEventParamControlOptimalBaselineOffset, typeShortInteger, baseLine ); +						} +					} +					break; +				 +				case kEventControlBoundsChanged: +					{ +						HIRect		prevRect, currRect; +						UInt32		attrs; +						 +						inEvent.GetParameter( kEventParamAttributes, &attrs ); +						inEvent.GetParameter( kEventParamOriginalBounds, &prevRect ); +						inEvent.GetParameter( kEventParamCurrentBounds, &currRect ); +						inEvent.GetParameter( kEventParamControlInvalRgn, &invalRgn ); + +						result = BoundsChanged( attrs, prevRect, currRect, invalRgn ); + +						if ( mouseEventHandler != NULL ) +							{ +							ActivateInterface( kMouse ); +							} + +					} +					break; + +				case kEventControlHit: +					{ +						UInt32		modifiers; +						 +						inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part ); +						inEvent.GetParameter( kEventParamKeyModifiers, &modifiers ); +	 +						result = ControlHit( part, modifiers ); +					} +					break; +				 +				case kEventControlHiliteChanged: +					{ +						ControlPartCode	prevPart, currPart; +						 +						inEvent.GetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, &prevPart ); +						inEvent.GetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, &currPart ); +						inEvent.GetParameter( kEventParamControlInvalRgn, &invalRgn ); + +						result = HiliteChanged( prevPart, currPart, invalRgn ); +						 +						if ( GetAutoInvalidateFlags() & kAutoInvalidateOnHilite ) +							Invalidate(); +					} +					break; +					 +				case kEventControlActivate: +					result = ActiveStateChanged(); + +					if ( GetAutoInvalidateFlags() & kAutoInvalidateOnActivate ) +						Invalidate(); +					break; +					 +				case kEventControlDeactivate: +					result = ActiveStateChanged(); + +					if ( GetAutoInvalidateFlags() & kAutoInvalidateOnActivate ) +						Invalidate(); +					break; +					 +				case kEventControlValueFieldChanged: +					result = ValueChanged(); + +					if ( GetAutoInvalidateFlags() & kAutoInvalidateOnValueChange ) +						Invalidate(); +					break; +					 +				case kEventControlTitleChanged: +					result = TitleChanged(); + +					if ( GetAutoInvalidateFlags() & kAutoInvalidateOnTitleChange ) +						Invalidate(); +					break; +					 +				case kEventControlEnabledStateChanged: +					result = EnabledStateChanged(); + +					if ( GetAutoInvalidateFlags() & kAutoInvalidateOnEnable ) +						Invalidate(); +					break; +					 +				case kEventControlDragEnter: +				case kEventControlDragLeave: +				case kEventControlDragWithin: +					{ +						DragRef		drag; +						bool		likesDrag; +						 +						inEvent.GetParameter( kEventParamDragRef, &drag ); + +						switch ( inEvent.GetKind() ) +						{ +							case kEventControlDragEnter: +								likesDrag = DragEnter( drag ); +								// Why only if likesDrag?  What if it doesn't?  No parameter? +								if ( likesDrag ) +									result = inEvent.SetParameter( kEventParamControlLikesDrag, likesDrag ); +								break; +							 +							case kEventControlDragLeave: +								DragLeave( drag ); +								result = noErr; +								break; +							 +							case kEventControlDragWithin: +								DragWithin( drag ); +								result = noErr; +								break; +						} +					} +					break; +				 +				case kEventControlDragReceive: +					{ +						DragRef		drag; +						 +						inEvent.GetParameter( kEventParamDragRef, &drag ); + +						result = DragReceive( drag ); +					} +					break; +				 +				case kEventControlTrack: +					{ +						ControlPartCode		part; +						 +						result = Track( inEvent, &part ); +						if ( result == noErr ) +							verify_noerr( inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, part ) ); +					} +					break; + +				case kEventControlGetSizeConstraints: +					{ +						HISize		minSize, maxSize; +						 +						result = GetSizeConstraints( &minSize, &maxSize ); + +						if ( result == noErr ) +						{ +							verify_noerr( inEvent.SetParameter( kEventParamMinimumSize, minSize ) ); +							verify_noerr( inEvent.SetParameter( kEventParamMaximumSize, maxSize ) ); +						} +					} +					break; + +				case kEventControlSetFocusPart: +					{ +						ControlPartCode		desiredFocus; +						RgnHandle			invalidRgn; +						Boolean				focusEverything; +						ControlPartCode		actualFocus; +						 +						result = inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &desiredFocus );  +						require_noerr( result, MissingParameter ); +						 +						inEvent.GetParameter( kEventParamControlInvalRgn, &invalidRgn ); + +						focusEverything = false; // a good default in case the parameter doesn't exist + +						inEvent.GetParameter( kEventParamControlFocusEverything, &focusEverything ); + +						result = SetFocusPart( desiredFocus, invalidRgn, focusEverything, &actualFocus ); +						 +						if ( result == noErr ) +							verify_noerr( inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, actualFocus ) ); +					} +					break; + +				case kEventControlOwningWindowChanged: +					{ +						// If our owning window has changed, reactivate the mouse interface +						if ( mouseEventHandler != NULL ) +							{ +							ActivateInterface( kMouse ); +							} +					} +					break; + +				case kEventControlContextualMenuClick: +					{ +						HIPoint ptMouse; +						inEvent.GetParameter( kEventParamMouseLocation, &ptMouse ); +						result = ContextualMenuClick( ptMouse ); +					} +					break; +					 +				// some other kind of Control event +				default: +					assert( false ); +					break; +			} +			break; +			 +		case kEventClassTextInput: +			result = TextInput( inEvent ); +			break; + +		case kEventClassMouse: +			result = inEvent.GetParameter<HIPoint>( kEventParamWindowMouseLocation, typeHIPoint, &where ); +			HIViewConvertPoint( &where, NULL, fViewRef ); +			assert( result == noErr ); +			 +			UInt32 inKeyModifiers; +			result = inEvent.GetParameter( kEventParamKeyModifiers, &inKeyModifiers ); +			assert( result == noErr ); +			 +			switch ( inEvent.GetKind() ) +				{ +				case kEventMouseWheelMoved: +					{ +						EventMouseWheelAxis inAxis; +						result = inEvent.GetParameter<EventMouseWheelAxis>( kEventParamMouseWheelAxis, typeMouseWheelAxis, &inAxis ); +						assert( noErr == result ); + +						SInt32 inDelta; +						result = inEvent.GetParameter<SInt32>( kEventParamMouseWheelDelta, typeSInt32, &inDelta ); +						assert( noErr == result ); + +						result = MouseWheelMoved( inAxis, inDelta, inKeyModifiers );					 +					} +					break; +					 +					 +				// some other kind of Mouse event: This is (in my opinion) an error +				// TODO: There is also a MouseMoved event that we do not handle +				default: +					{ +						EventMouseButton inMouseButton; +						result = inEvent.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton ); +						assert( result == noErr ); + +						UInt32 inClickCount; +						result = inEvent.GetParameter( kEventParamClickCount, &inClickCount ); +						assert( result == noErr ); + +						switch ( inEvent.GetKind() ) +						  { +						  case kEventMouseDown: +						    result = MouseDown( where, inKeyModifiers, inMouseButton, inClickCount, inEvent ); +						    break; +						  case kEventMouseUp: +						    result = MouseUp( where, inKeyModifiers, inMouseButton, inClickCount ); +						    break; +						  case kEventMouseExited: +						    result = MouseExited( where, inKeyModifiers, inMouseButton, inClickCount ); +						    break; +						  case kEventMouseEntered: +						    result = MouseEntered( where, inKeyModifiers, inMouseButton, inClickCount ); +						    break; +						  case kEventMouseMoved: +						  case kEventMouseDragged: +						    result = MouseDragged( where, inKeyModifiers, inMouseButton, inClickCount ); +						    break; +						  } +					} +					break; +				} +				break; +			 +		// some other event class +		default: +			assert( false ); +			break; +	} + +MissingParameter: +	return result; +} + +//----------------------------------------------------------------------------------- +//	CreateInitializationEvent +//----------------------------------------------------------------------------------- +// 	Create a basic intialization event containing the parent control and bounds. At +//	present we set the bounds to empty and the parent to NULL. In theory, after creating +//	this event, any subclass could add its own parameter to receive in its +//	Initialize method. +// +EventRef TView::CreateInitializationEvent() +{ +	OSStatus		result = noErr; +	EventRef		event; + +	result = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, +					GetCurrentEventTime(), 0, &event ); +	require_noerr_action( result, CantCreateEvent, event = NULL ); +		 +CantCreateEvent: +	return event; +} + +//----------------------------------------------------------------------------------- +//	Frame +//----------------------------------------------------------------------------------- +// +HIRect TView::Frame() +{ +	HIRect		frame; + +	HIViewGetFrame( GetViewRef(), &frame ); +	 +	return frame; +} + +//----------------------------------------------------------------------------------- +//	SetFrame +//----------------------------------------------------------------------------------- +// +OSStatus TView::SetFrame( +	const HIRect&			inFrame ) +{ +	OSStatus				err; +	 +	err = HIViewSetFrame( GetViewRef(), &inFrame ); +	 +	return err; +} + +//----------------------------------------------------------------------------------- +//	Bounds +//----------------------------------------------------------------------------------- +// +HIRect TView::Bounds() +{ +	HIRect		bounds; +	 +	HIViewGetBounds( GetViewRef(), &bounds ); +	 +	return bounds; +} + +//----------------------------------------------------------------------------------- +//	Show +//----------------------------------------------------------------------------------- +// +OSStatus TView::Show() +{ +	return HIViewSetVisible( GetViewRef(), true ); +} + +//----------------------------------------------------------------------------------- +//	Hide +//----------------------------------------------------------------------------------- +// +OSStatus TView::Hide() +{ +	return HIViewSetVisible( GetViewRef(), false ); +} + +//----------------------------------------------------------------------------------- +//	GetEventTarget +//----------------------------------------------------------------------------------- +// +EventTargetRef TView::GetEventTarget() +{ +	return HIObjectGetEventTarget( (HIObjectRef) GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	AddSubView +//----------------------------------------------------------------------------------- +// +OSStatus TView::AddSubView( +	TView*				inSubView ) +{ +	return HIViewAddSubview( GetViewRef(), inSubView->GetViewRef() );; +} + +//----------------------------------------------------------------------------------- +//	RemoveFromSuperView +//----------------------------------------------------------------------------------- +// +OSStatus TView::RemoveFromSuperView() +{ +	return HIViewRemoveFromSuperview( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	GetHilite +//----------------------------------------------------------------------------------- +// +ControlPartCode TView::GetHilite() +{ +	return GetControlHilite( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	GetValue +//----------------------------------------------------------------------------------- +// +SInt32 TView::GetValue() +{ +	return GetControl32BitValue( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	SetValue +//----------------------------------------------------------------------------------- +// +void TView::SetValue( +	SInt32					inValue ) +{ +	SetControl32BitValue( GetViewRef(), inValue ); +} + +//----------------------------------------------------------------------------------- +//	GetMinimum +//----------------------------------------------------------------------------------- +// +SInt32 TView::GetMinimum() +{ +	return GetControlMinimum( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	SetMinimum +//----------------------------------------------------------------------------------- +// +void TView::SetMinimum( +	SInt32					inMinimum ) +{ +	SetControlMinimum( GetViewRef(), inMinimum ); +} + +//----------------------------------------------------------------------------------- +//	GetMaximum +//----------------------------------------------------------------------------------- +// +SInt32 TView::GetMaximum() +{ +	return GetControlMaximum( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	SetMaximum +//----------------------------------------------------------------------------------- +// +void TView::SetMaximum( +	SInt32					inMaximum ) +{ +	SetControlMaximum( GetViewRef(), inMaximum ); +} + +//----------------------------------------------------------------------------------- +//	GetOwner +//----------------------------------------------------------------------------------- +// +WindowRef TView::GetOwner() +{ +	return GetControlOwner( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	Hilite +//----------------------------------------------------------------------------------- +// +void TView::Hilite( +	ControlPartCode			inPart) +{ +	return HiliteControl( GetViewRef(), inPart ); +} + +//----------------------------------------------------------------------------------- +//	Invalidate +//----------------------------------------------------------------------------------- +// +OSStatus TView::Invalidate() +{ +	return HIViewSetNeedsDisplay( GetViewRef(), true ); +} + +void TView::TimerFired( EventLoopTimerRef inTimer ) +{ +#pragma unused( inTimer ) +} + + +//----------------------------------------------------------------------------------- +//	IsVisible +//----------------------------------------------------------------------------------- +// +Boolean TView::IsVisible() +{ +	return IsControlVisible( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	IsEnabled +//----------------------------------------------------------------------------------- +// +Boolean TView::IsEnabled() +{ +	return IsControlEnabled( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	IsActive +//----------------------------------------------------------------------------------- +// +Boolean TView::IsActive() +{ +	return IsControlActive( GetViewRef() ); +} + +//----------------------------------------------------------------------------------- +//	ActiveStateChanged +//----------------------------------------------------------------------------------- +//	Default activation method. Subclasses should override as necessary. We do nothing +//	here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::ActiveStateChanged() +{ +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	ValueChanged +//----------------------------------------------------------------------------------- +//	Default value changed method. Subclasses should override as necessary. We do +//	nothing here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::ValueChanged() +{ +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	TitleChanged +//----------------------------------------------------------------------------------- +//	Default title changed method. Subclasses should override as necessary. We +//	do nothing here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::TitleChanged() +{ +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	EnabledStateChanged +//----------------------------------------------------------------------------------- +//	Default enable method. Subclasses should override as necessary. We +//	do nothing here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::EnabledStateChanged() +{ +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	TextInput +//----------------------------------------------------------------------------------- +//	Default text (Unicode) input method. Subclasses should override as necessary. We +//	do nothing here in the base class, so we return eventNotHandledErr. +// +OSStatus TView::TextInput( +	TCarbonEvent&		inEvent ) +{ +#pragma unused( inEvent ) + +	return eventNotHandledErr; +} + +//----------------------------------------------------------------------------------- +//	ChangeAutoInvalidateFlags +//----------------------------------------------------------------------------------- +//	Change behavior for auto-invalidating views on certain actions. +// +void TView::ChangeAutoInvalidateFlags( +	OptionBits			inSetThese, +	OptionBits			inClearThese ) +{ +    fAutoInvalidateFlags = ( ( fAutoInvalidateFlags | inSetThese ) & ( ~inClearThese ) ); +} diff --git a/macosx/TView.h b/macosx/TView.h new file mode 100644 index 000000000..97c8f7b55 --- /dev/null +++ b/macosx/TView.h @@ -0,0 +1,286 @@ +/* +	File:		TView.h + +    Version:	1.0 + +	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. +				("Apple") in consideration of your agreement to the following terms, and your +				use, installation, modification or redistribution of this Apple software +				constitutes acceptance of these terms.  If you do not agree with these terms, +				please do not use, install, modify or redistribute this Apple software. + +				In consideration of your agreement to abide by the following terms, and subject +				to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs +				copyrights in this original Apple software (the "Apple Software"), to use, +				reproduce, modify and redistribute the Apple Software, with or without +				modifications, in source and/or binary forms; provided that if you redistribute +				the Apple Software in its entirety and without modifications, you must retain +				this notice and the following text and disclaimers in all such redistributions of +				the Apple Software.  Neither the name, trademarks, service marks or logos of +				Apple Computer, Inc. may be used to endorse or promote products derived from the +				Apple Software without specific prior written permission from Apple.  Except as +				expressly stated in this notice, no other rights or licenses, express or implied, +				are granted by Apple herein, including but not limited to any patent rights that +				may be infringed by your derivative works or by other works in which the Apple +				Software may be incorporated. + +				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO +				WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +				WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +				PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +				COMBINATION WITH YOUR PRODUCTS. + +				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +				CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +				GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +				ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +				OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +				(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +				ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +	Copyright © 2002 Apple Computer, Inc., All Rights Reserved +*/ + +#ifndef TView_H_ +#define TView_H_ + +#include <Carbon/Carbon.h> + +#include "TCarbonEvent.h" +#include "TRect.h" + +#define PURE_VIRTUAL 0 + +class TView +{ +public: +	// Bounds and Frame +	OSStatus				SetFrame( +								const HIRect&		inBounds ); +	HIRect					Frame(); +	HIRect					Bounds(); +	 +	// Visibility +	OSStatus				Show(); +	OSStatus				Hide(); + +	EventTargetRef			GetEventTarget(); + +	OSStatus				AddSubView( +								TView*				inSubView ); +	OSStatus				RemoveFromSuperView(); + +	// Accessors +	HIViewRef				GetViewRef() const +								{ return fViewRef; } +	void					Hilite( +								ControlPartCode		inPart ); +	ControlPartCode			GetHilite(); +	WindowRef				GetOwner(); +	SInt32					GetValue(); +	void					SetValue( +								SInt32				inValue ); +	SInt32					GetMinimum(); +	void					SetMinimum( +								SInt32				inMinimum ); +	SInt32					GetMaximum(); +	void					SetMaximum( +								SInt32				inMaximum ); + +	// State +	Boolean					IsVisible(); +	Boolean					IsEnabled(); +	Boolean					IsActive(); +	 +	OSStatus				Invalidate();		// was SetNeedsDisplay() + +	// A "fake" event handler +	virtual void			TimerFired( EventLoopTimerRef inTimer ); + +protected: +	// Autoinvalidation +	enum					{  +								kAutoInvalidateOnActivate 		= (1 << 0), +								kAutoInvalidateOnHilite			= (1 << 1), +								kAutoInvalidateOnEnable			= (1 << 2), +								kAutoInvalidateOnValueChange	= (1 << 3), +								kAutoInvalidateOnTitleChange	= (1 << 4) +							}; +	void					ChangeAutoInvalidateFlags( +								OptionBits			inSetFlags, +								OptionBits			inClearFlags ); +	OptionBits				GetAutoInvalidateFlags() +								{ return fAutoInvalidateFlags; } + +	// Types +	typedef OSStatus		(*ConstructProc)( +								ControlRef			inBaseControl, +								TView**				outView ); + +	// Construction/Destruction +							TView( HIViewRef inControl ); +	virtual					~TView(); +	 +	virtual ControlKind		GetKind() = PURE_VIRTUAL; +	virtual UInt32			GetBehaviors(); + +	// Handlers +	virtual OSStatus		ActiveStateChanged(); +	virtual OSStatus		BoundsChanged( +								UInt32				inOptions, +								const HIRect&		inOriginalBounds, +								const HIRect&		inCurrentBounds, +								RgnHandle			inInvalRgn ); +	virtual OSStatus		ControlHit( +								ControlPartCode		inPart, +								UInt32				inModifiers ); +	virtual OSStatus		EnabledStateChanged(); +	virtual void			Draw( +								RgnHandle			inLimitRgn, +								CGContextRef		inContext ); +	virtual OSStatus		GetData( +								OSType				inTag, +								ControlPartCode		inPart, +								Size				inSize, +								Size*				outSize, +								void*				inPtr ); +	virtual OSStatus		GetRegion( +								ControlPartCode		inPart, +								RgnHandle			outRgn ); +	virtual OSStatus		HiliteChanged( +								ControlPartCode		inOriginalPart, +								ControlPartCode		inCurrentPart, +								RgnHandle			inInvalRgn ); +	virtual ControlPartCode	HitTest( +								const HIPoint&		inWhere ); +	virtual OSStatus		Initialize( +								TCarbonEvent&		inEvent ); +	virtual OSStatus		SetData( +								OSType				inTag, +								ControlPartCode		inPart, +								Size				inSize, +								const void*			inPtr ); +	virtual OSStatus		SetFocusPart( +								ControlPartCode		inDesiredFocus, +								RgnHandle			inNnvalidRgn, +								Boolean				inFocusEverything, +								ControlPartCode*	outActualFocus ); +	virtual OSStatus		TextInput( +								TCarbonEvent&		inEvent ); +	virtual OSStatus		TitleChanged(); +	virtual OSStatus		Track( +								TCarbonEvent&		inEvent, +								ControlPartCode*	outPartHit ); +	virtual OSStatus		ValueChanged(); +	 +	// Sizing +	virtual OSStatus		GetSizeConstraints( +								HISize*				outMin, +								HISize*				outMax ); +	virtual OSStatus		GetOptimalSize( +								HISize*				outSize, +								float*				outBaseLine ); + +	// Accessors +	WindowRef				GetWindowRef() +								{ return GetControlOwner( GetViewRef() ); } +	 +	 +	// Drag and drop +	virtual bool			DragEnter( +								DragRef				inDrag ); +	virtual bool			DragWithin( +								DragRef				inDrag ); +	virtual bool			DragLeave( +								DragRef				inDrag ); +	virtual OSStatus		DragReceive( +								DragRef				inDrag ); + +	// Command processing +	virtual OSStatus		ProcessCommand( +								const HICommand&	inCommand ); +	virtual OSStatus		UpdateCommandStatus( +								const HICommand&	inCommand ); + +	// Mouse events +	virtual OSStatus		MouseDown( +								HIPoint& inMouseLocation, +								UInt32 inKeyModifiers, +								EventMouseButton inMouseButton, +								UInt32 inClickCount, +								TCarbonEvent& inEvent); +	virtual OSStatus		MouseUp( +								HIPoint& inMouseLocation, +								UInt32 inKeyModifiers, +								EventMouseButton inMouseButton, +								UInt32 inClickCount ); +	virtual OSStatus		MouseDragged( +								HIPoint& inMouseLocation, +								UInt32 inKeyModifiers, +								EventMouseButton inMouseButton, +								UInt32 inClickCount ); +	virtual OSStatus		MouseEntered( +								HIPoint& inMouseLocation, +								UInt32 inKeyModifiers, +								EventMouseButton inMouseButton, +								UInt32 inClickCount ); +	virtual OSStatus		MouseExited( +								HIPoint& inMouseLocation, +								UInt32 inKeyModifiers, +								EventMouseButton inMouseButton, +								UInt32 inClickCount ); +	virtual OSStatus 		MouseWheelMoved( EventMouseWheelAxis inAxis, SInt32 inDelta, UInt32 inKeyModifiers ); +	virtual OSStatus		ContextualMenuClick( HIPoint& inMouseLocation ); +	 +	// Utility +	static OSStatus			RegisterSubclass( +								CFStringRef			inID, +								ConstructProc		inProc ); +	static EventRef			CreateInitializationEvent(); +	enum Interface			{ +								kDragAndDrop		= 1, +								kKeyboardFocus, +								kMouse, +								kMouseTracking +							}; +	virtual OSStatus		ActivateInterface( +								Interface			inInterface ); + +	OSStatus				InstallTimer( +								EventTimerInterval	inFireDelay, +								EventLoopTimerRef*	outTimer ); +	 +	// Debugging +	virtual void			PrintDebugInfo(); +	Boolean debugPrint; +private: +	static pascal OSStatus	ObjectEventHandler( +								EventHandlerCallRef	inCallRef, +								EventRef			inEvent, +								void*				inUserData ); +	static pascal OSStatus	ViewEventHandler( +								EventHandlerCallRef	inCallRef, +								EventRef			inEvent, +								void*				inUserData ); +	static pascal OSStatus	WindowEventHandler( +								EventHandlerCallRef	inCallRef, +								EventRef			inEvent, +								void*				inUserData ); +	static pascal void 		TimerEventHandler( +								EventLoopTimerRef	inTimer, +										void*		inUserData ); +	OSStatus				HandleEvent( +								EventHandlerCallRef	inCallRef, +								TCarbonEvent&		inEvent ); + +	HIViewRef				fViewRef; +	EventHandlerRef			fHandler; + +	EventHandlerRef			mouseEventHandler; +	OptionBits				fAutoInvalidateFlags; + +}; + +typedef TView*				TViewPtr; + +#endif // TView_H_ diff --git a/macosx/deps.mak b/macosx/deps.mak new file mode 100644 index 000000000..5c65dcc1f --- /dev/null +++ b/macosx/deps.mak @@ -0,0 +1,315 @@ +PlatMacOSX.o: PlatMacOSX.cxx QuartzTextLayout.h QuartzTextStyle.h \ +  QuartzTextStyleAttribute.h TCarbonEvent.h ../include/Platform.h \ +  ../include/Scintilla.h PlatMacOSX.h ../src/XPM.h \ +  ../include/ScintillaWidget.h +ScintillaCallTip.o: ScintillaCallTip.cxx ScintillaMacOSX.h TView.h \ +  TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \ +  PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \ +  QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \ +  ../include/SciLexer.h ../include/PropSet.h ../include/SString.h \ +  ../include/Accessor.h ../include/KeyWords.h ../src/ContractionState.h \ +  ../src/SVector.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \ +  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \ +  ../src/AutoComplete.h ../src/ViewStyle.h ../src/Document.h \ +  ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h +ScintillaListBox.o: ScintillaListBox.cxx ScintillaMacOSX.h TView.h \ +  TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \ +  PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \ +  QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \ +  ../include/SciLexer.h ../include/PropSet.h ../include/SString.h \ +  ../include/Accessor.h ../include/KeyWords.h ../src/ContractionState.h \ +  ../src/SVector.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \ +  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \ +  ../src/AutoComplete.h ../src/ViewStyle.h ../src/Document.h \ +  ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h \ +  ScintillaListBox.h +ScintillaMacOSX.o: ScintillaMacOSX.cxx ScintillaMacOSX.h TView.h \ +  TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \ +  PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \ +  QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \ +  ../include/SciLexer.h ../include/PropSet.h ../include/SString.h \ +  ../include/Accessor.h ../include/KeyWords.h ../src/ContractionState.h \ +  ../src/SVector.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \ +  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \ +  ../src/AutoComplete.h ../src/ViewStyle.h ../src/Document.h \ +  ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h \ +  ../src/UniConversion.h +TCarbonEvent.o: TCarbonEvent.cxx TCarbonEvent.h +TView.o: TView.cxx TView.h TCarbonEvent.h TRect.h +AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../src/AutoComplete.h +CallTip.o: ../src/CallTip.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/CallTip.h +CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \ +  ../src/Partitioning.h ../src/CellBuffer.h +CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h +ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \ +  ../src/ContractionState.h +Decoration.o: ../src/Decoration.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ +  ../src/RunStyles.h ../src/Decoration.h +Document.o: ../src/Document.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \ +  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \ +  ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \ +  ../src/RESearch.h +DocumentAccessor.o: ../src/DocumentAccessor.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../src/SVector.h \ +  ../include/Accessor.h ../src/DocumentAccessor.h ../src/SplitVector.h \ +  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \ +  ../include/Scintilla.h ../src/CharClassify.h ../src/Decoration.h \ +  ../src/Document.h +Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \ +  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \ +  ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \ +  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ +  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \ +  ../src/Decoration.h ../src/Document.h ../src/Editor.h +ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/DocumentAccessor.h \ +  ../include/KeyWords.h ../src/ExternalLexer.h +Indicator.o: ../src/Indicator.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/Indicator.h +KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \ +  ../src/KeyMap.h +KeyWords.o: ../src/KeyWords.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexAPDL.o: ../src/LexAPDL.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexAU3.o: ../src/LexAU3.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexAVE.o: ../src/LexAVE.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexAda.o: ../src/LexAda.cxx ../include/Platform.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/PropSet.h ../include/SString.h \ +  ../include/KeyWords.h ../include/SciLexer.h +LexAsm.o: ../src/LexAsm.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexAsn1.o: ../src/LexAsn1.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexBaan.o: ../src/LexBaan.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexBash.o: ../src/LexBash.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexBasic.o: ../src/LexBasic.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexBullant.o: ../src/LexBullant.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCLW.o: ../src/LexCLW.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCPP.o: ../src/LexCPP.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCSS.o: ../src/LexCSS.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCaml.o: ../src/LexCaml.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCmake.o: ../src/LexCmake.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexConf.o: ../src/LexConf.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexCrontab.o: ../src/LexCrontab.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexCsound.o: ../src/LexCsound.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexD.o: ../src/LexD.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexEScript.o: ../src/LexEScript.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexEiffel.o: ../src/LexEiffel.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexErlang.o: ../src/LexErlang.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexFlagship.o: ../src/LexFlagship.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexForth.o: ../src/LexForth.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexFortran.o: ../src/LexFortran.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexGAP.o: ../src/LexGAP.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexGui4Cli.o: ../src/LexGui4Cli.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexHTML.o: ../src/LexHTML.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexHaskell.o: ../src/LexHaskell.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexInno.o: ../src/LexInno.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexKix.o: ../src/LexKix.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexLisp.o: ../src/LexLisp.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h +LexLout.o: ../src/LexLout.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexLua.o: ../src/LexLua.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexMMIXAL.o: ../src/LexMMIXAL.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexMPT.o: ../src/LexMPT.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexMSSQL.o: ../src/LexMSSQL.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexMatlab.o: ../src/LexMatlab.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexMetapost.o: ../src/LexMetapost.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \ +  ../src/StyleContext.h +LexNsis.o: ../src/LexNsis.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexOpal.o: ../src/LexOpal.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h +LexOthers.o: ../src/LexOthers.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexPB.o: ../src/LexPB.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexPOV.o: ../src/LexPOV.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexPS.o: ../src/LexPS.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexPascal.o: ../src/LexPascal.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \ +  ../src/StyleContext.h +LexPerl.o: ../src/LexPerl.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexPython.o: ../src/LexPython.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexRebol.o: ../src/LexRebol.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \ +  ../src/StyleContext.h +LexRuby.o: ../src/LexRuby.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h +LexSQL.o: ../src/LexSQL.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexScriptol.o: ../src/LexScriptol.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexSmalltalk.o: ../src/LexSmalltalk.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexSpecman.o: ../src/LexSpecman.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexSpice.o: ../src/LexSpice.cxx ../include/Platform.h \ +  ../include/Accessor.h ../src/StyleContext.h ../include/PropSet.h \ +  ../include/SString.h ../include/KeyWords.h ../include/SciLexer.h +LexTADS3.o: ../src/LexTADS3.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexTCL.o: ../src/LexTCL.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexTeX.o: ../src/LexTeX.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../include/KeyWords.h \ +  ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h +LexVB.o: ../src/LexVB.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexVHDL.o: ../src/LexVHDL.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LexVerilog.o: ../src/LexVerilog.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \ +  ../include/SciLexer.h +LexYAML.o: ../src/LexYAML.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h ../include/Accessor.h ../src/StyleContext.h \ +  ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h +LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h +PropSet.o: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h \ +  ../include/SString.h +RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h +RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ +  ../src/RunStyles.h +ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../include/PropSet.h ../include/SString.h \ +  ../include/SciLexer.h ../include/Accessor.h ../src/DocumentAccessor.h \ +  ../include/KeyWords.h ../src/ContractionState.h ../src/SVector.h \ +  ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \ +  ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \ +  ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \ +  ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \ +  ../src/Document.h ../src/Editor.h ../src/ScintillaBase.h +Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \ +  ../src/Style.h +StyleContext.o: ../src/StyleContext.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../src/StyleContext.h +UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h +ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \ +  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \ +  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \ +  ../src/Style.h ../src/ViewStyle.h +WindowAccessor.o: ../src/WindowAccessor.cxx ../include/Platform.h \ +  ../include/PropSet.h ../include/SString.h ../include/Accessor.h \ +  ../include/WindowAccessor.h ../include/Scintilla.h +XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h diff --git a/macosx/makefile b/macosx/makefile new file mode 100644 index 000000000..0ddbb9ccc --- /dev/null +++ b/macosx/makefile @@ -0,0 +1,95 @@ +# Make file for Scintilla on Mac OS X +# Copyright 2002 by Evan Jones <ejones@uwaterloo.ca> +# Based on the GTK makefile Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +# The License.txt file describes the conditions under which this software may be distributed. +# This makefile assumes that Apple's version of GCC 3.1 is used and changes will be needed to use other compilers. +# GNU make does not like \r\n line endings so should be saved to CVS in binary form. + +.SUFFIXES: .cxx .c .o .h .a +CC = c++ +CCOMP = gcc +LIBTOOL = libtool + +GCC_MAJOR    := $(shell $(CC) -v 2>&1 | \ +                        grep version | cut -d' ' -f3  | cut -d'.' -f1) + +# We call it "libscintilla" so when you add it to a Project Builder project, +# Project Builder will link it correctly. +COMPLIB=../bin/libscintilla.a + +vpath %.h ../src ../include +vpath %.cxx ../src + +INCLUDEDIRS=-I ../include -I ../src + +ifeq ($(GCC_MAJOR),3) +# 10.4 will have GCC 4 or better, so this should only ever happen +# on a 10.3 or older PPC box +ARCHFLAGS=-arch ppc -faltivec -mcpu=7400 -mtune=7400 -mpowerpc -mpowerpc-gfxopt +else +ARCHFLAGS=-isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 +LDFLAGS=/usr/include/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 +endif + +OPTIONS=-Wall -Wno-missing-braces -Wno-char-subscripts -DSCI_NAMESPACE -DMACOSX -DSCI_LEXER  + +#DEBUG = 1 + +ifdef DEBUG +DFLAGS=-DDEBUG -g +else +DFLAGS=-DNDEBUG -Os +endif + +ifdef CONTAINER_HANDLES_EVENTS +CONTAINER=-DCONTAINER_HANDLES_EVENTS=1 +endif + +.cxx.o: +	$(CC) $(CXXFLAGS) $(OPTIONS) $(DFLAGS) $(CONTAINER) $(ARCHFLAGS) $(INCLUDEDIRS) -c $< +.c.o: +	$(CCOMP) $(CXXFLAGS) $(OPTIONS) $(DFLAGS) $(CONTAINER) $(ARCHFLAGS) $(INCLUDEDIRS) -w -c $< + +#++Autogenerated -- run src/LexGen.py to regenerate +#**LEXOBJS=\\\n\(\*.o \) +LEXOBJS=\ +LexAda.o LexAPDL.o LexAsm.o LexAsn1.o LexAU3.o LexAVE.o LexBaan.o LexBash.o \ +LexBasic.o LexBullant.o LexCaml.o LexCLW.o LexCmake.o LexConf.o LexCPP.o \ +LexCrontab.o LexCsound.o LexCSS.o LexD.o LexEiffel.o LexErlang.o LexEScript.o \ +LexFlagship.o LexForth.o LexFortran.o LexGAP.o LexGui4Cli.o LexHaskell.o \ +LexHTML.o LexInno.o LexKix.o LexLisp.o LexLout.o LexLua.o LexMatlab.o \ +LexMetapost.o LexMMIXAL.o LexMPT.o LexMSSQL.o LexNsis.o LexOpal.o LexOthers.o \ +LexPascal.o LexPB.o LexPerl.o LexPOV.o LexPS.o LexPython.o LexRebol.o \ +LexRuby.o LexScriptol.o LexSmalltalk.o LexSpecman.o LexSpice.o LexSQL.o \ +LexTADS3.o LexTCL.o LexTeX.o LexVB.o LexVerilog.o LexVHDL.o LexYAML.o +#--Autogenerated -- end of automatically generated section + +# The LEXOBJS have to be treated specially as the functions in them are not called from external code + +all: $(COMPLIB) $(LEXOBJS) + +clean: +	rm -f *.o $(COMPLIB) + +deps: +	$(CC) -MM $(CXXFLAGS) *.cxx ../src/*.cxx >deps.mak + +$(COMPLIB): DocumentAccessor.o WindowAccessor.o KeyWords.o StyleContext.o \ +	CharClassify.o Decoration.o Document.o CallTip.o \ +	ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSet.o PlatMacOSX.o \ +	KeyMap.o LineMarker.o ScintillaMacOSX.o CellBuffer.o ViewStyle.o \ +	RESearch.o RunStyles.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \ +        TCarbonEvent.o TView.o ScintillaCallTip.o \ +	$(LEXOBJS) +	$(LIBTOOL) -o $@ $^ + +# Generate header files from Scintilla.iface +../include/Scintilla_gen.h: ../include/HFacer.py ../include/Face.py ../include/Scintilla.iface +	cd ../include && python HFacer.py +../include/SciLexer_gen.h: ../include/HFacer.py ../include/Face.py ../include/Scintilla.iface +	cd ../include && python HFacer.py +../include/Scintilla.h: ../include/Scintilla_gen.h +../include/SciLexer.h: ../include/SciLexer_gen.h + +# Automatically generate header dependencies with "make deps" +include deps.mak | 
