aboutsummaryrefslogtreecommitdiffhomepage
path: root/macosx
diff options
context:
space:
mode:
authorscaraveo <devnull@localhost>2007-06-01 00:57:26 +0000
committerscaraveo <devnull@localhost>2007-06-01 00:57:26 +0000
commitbff5c376377f4c19a62e6a44eccda7dbe9deebaf (patch)
tree55e5547869daa67b6a639c89825058baf75545c7 /macosx
parent664fee964e1f91132ebf07a4b122e59c1e932ea6 (diff)
downloadscintilla-mirror-bff5c376377f4c19a62e6a44eccda7dbe9deebaf.tar.gz
integrate OS X support for scintilla. a big patch with a little commit message :)
- now uses namespaces (optionally for non-os x) to avoid conflicts with OS X libraries - several fixes in the OS X layer since the branch was commited in 2005 - used in Komodo since 2005, so pretty stable
Diffstat (limited to 'macosx')
-rw-r--r--macosx/PlatMacOSX.cxx1922
-rw-r--r--macosx/PlatMacOSX.h101
-rw-r--r--macosx/QuartzTextLayout.h130
-rw-r--r--macosx/QuartzTextStyle.h105
-rw-r--r--macosx/QuartzTextStyleAttribute.h146
-rw-r--r--macosx/SciTest/English.lproj/InfoPlist.stringsbin0 -> 256 bytes
-rw-r--r--macosx/SciTest/Info.plist24
-rw-r--r--macosx/SciTest/SciTest.xcode/project.pbxproj287
-rw-r--r--macosx/SciTest/SciTest_Prefix.pch5
-rw-r--r--macosx/SciTest/main.cpp225
-rw-r--r--macosx/SciTest/version.plist16
-rw-r--r--macosx/ScintillaCallTip.cxx117
-rw-r--r--macosx/ScintillaCallTip.h64
-rw-r--r--macosx/ScintillaListBox.cxx103
-rw-r--r--macosx/ScintillaListBox.h63
-rw-r--r--macosx/ScintillaMacOSX.cxx2118
-rw-r--r--macosx/ScintillaMacOSX.h192
-rw-r--r--macosx/TCarbonEvent.cxx519
-rw-r--r--macosx/TCarbonEvent.h230
-rw-r--r--macosx/TRect.h496
-rw-r--r--macosx/TView.cxx1462
-rw-r--r--macosx/TView.h286
-rw-r--r--macosx/deps.mak315
-rw-r--r--macosx/makefile95
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.strings
new file mode 100644
index 000000000..4dcb4fe03
--- /dev/null
+++ b/macosx/SciTest/English.lproj/InfoPlist.strings
Binary files differ
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, &region );
+ 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, &region );
+ 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