diff options
Diffstat (limited to 'macosx/ScintillaMacOSX.cxx')
| -rw-r--r-- | macosx/ScintillaMacOSX.cxx | 2244 | 
1 files changed, 0 insertions, 2244 deletions
| diff --git a/macosx/ScintillaMacOSX.cxx b/macosx/ScintillaMacOSX.cxx deleted file mode 100644 index d1bee757f..000000000 --- a/macosx/ScintillaMacOSX.cxx +++ /dev/null @@ -1,2244 +0,0 @@ -// 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" -#ifdef EXT_INPUT -// External Input Editor -#include "ExtInput.h" -#else -#include "UniConversion.h" -#endif - -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; -} - -#ifdef EXT_INPUT -#define SCI_CMD ( SCI_ALT | SCI_CTRL | SCI_SHIFT) - -static const KeyToCommand macMapDefault[] = { -    {SCK_DOWN,		SCI_CMD,	SCI_DOCUMENTEND}, -    {SCK_UP,		SCI_CMD,	SCI_DOCUMENTSTART}, -    {SCK_LEFT,		SCI_CMD,	SCI_VCHOME}, -    {SCK_RIGHT,		SCI_CMD,	SCI_LINEEND}, -    {SCK_DOWN,		SCI_NORM,	SCI_LINEDOWN}, -    {SCK_DOWN,		SCI_SHIFT,	SCI_LINEDOWNEXTEND}, -    {SCK_DOWN,		SCI_CTRL,	SCI_LINESCROLLDOWN}, -    {SCK_DOWN,		SCI_ASHIFT,	SCI_LINEDOWNRECTEXTEND}, -    {SCK_UP,		SCI_NORM,	SCI_LINEUP}, -    {SCK_UP,			SCI_SHIFT,	SCI_LINEUPEXTEND}, -    {SCK_UP,			SCI_CTRL,	SCI_LINESCROLLUP}, -    {SCK_UP,		SCI_ASHIFT,	SCI_LINEUPRECTEXTEND}, -    {'[',			SCI_CTRL,		SCI_PARAUP}, -    {'[',			SCI_CSHIFT,	SCI_PARAUPEXTEND}, -    {']',			SCI_CTRL,		SCI_PARADOWN}, -    {']',			SCI_CSHIFT,	SCI_PARADOWNEXTEND}, -    {SCK_LEFT,		SCI_NORM,	SCI_CHARLEFT}, -    {SCK_LEFT,		SCI_SHIFT,	SCI_CHARLEFTEXTEND}, -    {SCK_LEFT,		SCI_ALT,	SCI_WORDLEFT}, -    {SCK_LEFT,		SCI_CSHIFT,	SCI_WORDLEFTEXTEND}, -    {SCK_LEFT,		SCI_ASHIFT,	SCI_CHARLEFTRECTEXTEND}, -    {SCK_RIGHT,		SCI_NORM,	SCI_CHARRIGHT}, -    {SCK_RIGHT,		SCI_SHIFT,	SCI_CHARRIGHTEXTEND}, -    {SCK_RIGHT,		SCI_ALT,	SCI_WORDRIGHT}, -    {SCK_RIGHT,		SCI_CSHIFT,	SCI_WORDRIGHTEXTEND}, -    {SCK_RIGHT,		SCI_ASHIFT,	SCI_CHARRIGHTRECTEXTEND}, -    {'/',		SCI_CTRL,		SCI_WORDPARTLEFT}, -    {'/',		SCI_CSHIFT,	SCI_WORDPARTLEFTEXTEND}, -    {'\\',		SCI_CTRL,		SCI_WORDPARTRIGHT}, -    {'\\',		SCI_CSHIFT,	SCI_WORDPARTRIGHTEXTEND}, -    {SCK_HOME,		SCI_NORM,	SCI_VCHOME}, -    {SCK_HOME, 		SCI_SHIFT, 	SCI_VCHOMEEXTEND}, -    {SCK_HOME, 		SCI_CTRL, 	SCI_DOCUMENTSTART}, -    {SCK_HOME, 		SCI_CSHIFT, 	SCI_DOCUMENTSTARTEXTEND}, -    {SCK_HOME, 		SCI_ALT, 	SCI_HOMEDISPLAY}, -//    {SCK_HOME,		SCI_ASHIFT,	SCI_HOMEDISPLAYEXTEND}, -    {SCK_HOME,		SCI_ASHIFT,	SCI_VCHOMERECTEXTEND}, -    {SCK_END,	 	SCI_NORM,	SCI_LINEEND}, -    {SCK_END,	 	SCI_SHIFT, 	SCI_LINEENDEXTEND}, -    {SCK_END, 		SCI_CTRL, 	SCI_DOCUMENTEND}, -    {SCK_END, 		SCI_CSHIFT, 	SCI_DOCUMENTENDEXTEND}, -    {SCK_END, 		SCI_ALT, 	SCI_LINEENDDISPLAY}, -//    {SCK_END,		SCI_ASHIFT,	SCI_LINEENDDISPLAYEXTEND}, -    {SCK_END,		SCI_ASHIFT,	SCI_LINEENDRECTEXTEND}, -    {SCK_PRIOR,		SCI_NORM,	SCI_PAGEUP}, -    {SCK_PRIOR,		SCI_SHIFT, 	SCI_PAGEUPEXTEND}, -    {SCK_PRIOR,		SCI_ASHIFT,	SCI_PAGEUPRECTEXTEND}, -    {SCK_NEXT, 		SCI_NORM, 	SCI_PAGEDOWN}, -    {SCK_NEXT, 		SCI_SHIFT, 	SCI_PAGEDOWNEXTEND}, -    {SCK_NEXT,		SCI_ASHIFT,	SCI_PAGEDOWNRECTEXTEND}, -    {SCK_DELETE, 	SCI_NORM,	SCI_CLEAR}, -    {SCK_DELETE, 	SCI_SHIFT,	SCI_CUT}, -    {SCK_DELETE, 	SCI_CTRL,	SCI_DELWORDRIGHT}, -    {SCK_DELETE,	SCI_CSHIFT,	SCI_DELLINERIGHT}, -    {SCK_INSERT, 		SCI_NORM,	SCI_EDITTOGGLEOVERTYPE}, -    {SCK_INSERT, 		SCI_SHIFT,	SCI_PASTE}, -    {SCK_INSERT, 		SCI_CTRL,	SCI_COPY}, -    {SCK_ESCAPE,  	SCI_NORM,	SCI_CANCEL}, -    {SCK_BACK,		SCI_NORM, 	SCI_DELETEBACK}, -    {SCK_BACK,		SCI_SHIFT, 	SCI_DELETEBACK}, -    {SCK_BACK,		SCI_CTRL, 	SCI_DELWORDLEFT}, -    {SCK_BACK, 		SCI_ALT,	SCI_UNDO}, -    {SCK_BACK,		SCI_CSHIFT,	SCI_DELLINELEFT}, -    {'Z', 			SCI_CTRL,	SCI_UNDO}, -    {'Y', 			SCI_CTRL,	SCI_REDO}, -    {'X', 			SCI_CTRL,	SCI_CUT}, -    {'C', 			SCI_CTRL,	SCI_COPY}, -    {'V', 			SCI_CTRL,	SCI_PASTE}, -    {'A', 			SCI_CTRL,	SCI_SELECTALL}, -    {SCK_TAB,		SCI_NORM,	SCI_TAB}, -    {SCK_TAB,		SCI_SHIFT,	SCI_BACKTAB}, -    {SCK_RETURN, 	SCI_NORM,	SCI_NEWLINE}, -    {SCK_RETURN, 	SCI_SHIFT,	SCI_NEWLINE}, -    {SCK_ADD, 		SCI_CTRL,	SCI_ZOOMIN}, -    {SCK_SUBTRACT,	SCI_CTRL,	SCI_ZOOMOUT}, -    {SCK_DIVIDE,	SCI_CTRL,	SCI_SETZOOM}, -    //'L', 			SCI_CTRL,		SCI_FORMFEED, -    {'L', 			SCI_CTRL,	SCI_LINECUT}, -    {'L', 			SCI_CSHIFT,	SCI_LINEDELETE}, -    {'T', 			SCI_CSHIFT,	SCI_LINECOPY}, -    {'T', 			SCI_CTRL,	SCI_LINETRANSPOSE}, -    {'D', 			SCI_CTRL,	SCI_SELECTIONDUPLICATE}, -    {'U', 			SCI_CTRL,	SCI_LOWERCASE}, -    {'U', 			SCI_CSHIFT,	SCI_UPPERCASE}, -    {0,0,0}, -}; -#endif - -ScintillaMacOSX::ScintillaMacOSX( void* windowid ) : -        TView( reinterpret_cast<HIViewRef>( windowid ) ) -{ -    notifyObj = NULL; -    notifyProc = NULL; -    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); -#ifdef EXT_INPUT -    ExtInput::attach (GetViewRef()); -    for (int i = 0; macMapDefault[i].key; i++) -    { -        this->kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg); -    } -#endif -} - -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); -#ifdef EXT_INPUT -    ExtInput::detach (GetViewRef()); -#endif -} - -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() { -    if (sel.Empty()) return; - -    // calculate the bounds of the selection -        PRectangle client = GetTextRectangle(); -    int selStart = sel.RangeMain().Start().Position(); -    int selEnd = sel.RangeMain().End().Position(); -    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 ); -            paintingAllText = true; -            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); - -    SelectionText selectedText; -    CopySelectionRange(&selectedText); -    PasteboardRef theClipboard; -    SetPasteboardData(theClipboard, selectedText, true); -    NewDragWithPasteboard( theClipboard, &inDrag); -    CFRelease( theClipboard ); - -    //  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. -    inDragDrop = ddDragging; -    OSErr error = TrackDrag(inDrag, &mouseDownEvent, dragRegion); -    inDragDrop = ddNone; - -    //  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); - -    if (pixmap) { -        CGImageRelease(image); -        pixmap->Release(); -        delete pixmap; -    } -} - -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); -    HIPoint hiPoint = GetLocalPoint (globalMouse); -    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.IsValid()) { -        RESET_SCROLL_TIMER(1); -        return; -    } -    Point dragMouse = LocationFromPosition(posDrag); -    int line = pdoc->LineFromPosition(posDrag.Position()); -    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(SPositionFromLocation(dragMouse)); - -#undef RESET_SCROLL_TIMER -} - -bool ScintillaMacOSX::DragWithin(DragRef inDrag ) -{ -    PasteboardRef pasteBoard; -    bool isFileURL = false; -    if (!GetDragData(inDrag, pasteBoard, NULL, &isFileURL)) { -        return false; -    } - -    Point pt = GetDragPoint (inDrag); -    SetDragPosition(SPositionFromLocation(pt)); -    SetDragCursor(inDrag); - -    return true; -} - -bool ScintillaMacOSX::DragLeave(DragRef inDrag ) -{ -    HideDragHilite( inDrag ); -    SetDragPosition(SelectionPosition(invalidPosition)); -    WndProc(SCI_SETCURSOR, Window::cursorArrow, 0); -    return true; -} - -enum -{ -    kFormatBad, -    kFormatText, -    kFormatUnicode, -    kFormatUTF8, -    kFormatFile -}; - -bool ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, -                                  SelectionText *selectedText, bool *isFileURL) -{ -  // 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 false; -    } -    return GetPasteboardData(pasteBoard, selectedText, isFileURL); -} - -void ScintillaMacOSX::SetPasteboardData(PasteboardRef &theClipboard, const SelectionText &selectedText, bool inDragDropSession) -{ -    if (selectedText.len == 0) -        return; - -    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman); - -    // 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 ); - -    PasteboardCreate((inDragDropSession -                      ? kPasteboardUniqueName -                      : kPasteboardClipboard), &theClipboard ); -    PasteboardClear( theClipboard ); - -    CFDataRef data = NULL; -    if (selectedText.rectangular) { -        // This is specific to scintilla, allows us to drag rectangular selections -        // around the document -        data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingUnicode, 0 ); -        if (data) { -            PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1, -                              CFSTR("com.scintilla.utf16-plain-text.rectangular"), -                              data, 0 ); -            CFRelease(data); -        } -    } -    data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingUnicode, 0 ); -    if (data) { -        PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1, -                                CFSTR("public.utf16-plain-text"), -                                data, 0 ); -        CFRelease(data); -        data = NULL; -    } -    data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingMacRoman, 0 ); -    if (data) { -        PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1, -                                CFSTR("com.apple.traditional-mac-plain-text"), -                                data, 0 ); -        CFRelease(data); -        data = NULL; -    } -    CFRelease(string); -} - -bool ScintillaMacOSX::GetPasteboardData(PasteboardRef &pasteBoard, -                                        SelectionText *selectedText, -                                        bool *isFileURL) -{ -    // how many items in the pasteboard? -    CFDataRef data; -    CFStringRef textString = NULL; -    bool isRectangular = selectedText ? selectedText->rectangular : false; -    ItemCount i, itemCount; -    OSStatus status = PasteboardGetItemCount(pasteBoard, &itemCount); -    if (status != noErr) { -        return false; -    } - -    // 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 false; -        } - -        // how many flavors in this item? -        status = PasteboardCopyItemFlavors(pasteBoard, itemID, &flavorTypeArray); -        if (status != noErr) { -            return false; -        } - -        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) -            { -                int format = kFormatBad; -                if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) { -                    format = kFormatFile; -                    *isFileURL = true; -                } -                else if (UTTypeConformsTo(flavorType, CFSTR("com.scintilla.utf16-plain-text.rectangular"))) { -                    format = kFormatUnicode; -                    isRectangular = true; -                } -                else if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))) { // this is 'utxt' -                    format = kFormatUnicode; -                } -                else if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text"))) { -                    format = kFormatUTF8; -                } -                else if (UTTypeConformsTo(flavorType, CFSTR("com.apple.traditional-mac-plain-text"))) { // this is 'TEXT' -                    format = kFormatText; -                } -                if (format == kFormatBad) -                    continue; - -                // if we got a flavor match, and we have no textString, we just want -                // to know that we can accept this data, so jump out now -                if (selectedText == NULL) { -                    haveMatch = true; -                    goto PasteboardDataRetrieved; -                } -                if (PasteboardCopyItemFlavorData(pasteBoard, itemID, flavorType, &flavorData) == noErr) -                { -                    CFIndex dataSize = CFDataGetLength (flavorData); -                    const UInt8* dataBytes = CFDataGetBytePtr (flavorData); -                    switch (format) -                    { -                        case kFormatFile: -                        case kFormatText: -                            data = CFDataCreate (NULL, dataBytes, dataSize); -                            textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingMacRoman); -                            break; -                        case kFormatUnicode: -                            data = CFDataCreate (NULL, dataBytes, dataSize); -                            textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingUnicode); -                            break; -                        case kFormatUTF8: -                            data = CFDataCreate (NULL, dataBytes, dataSize); -                            textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingUTF8); -                            break; -                    } -                    CFRelease (flavorData); -                    goto PasteboardDataRetrieved; -                } -            } -        } -    } -PasteboardDataRetrieved: -    if (flavorTypeArray != NULL) CFRelease(flavorTypeArray); -        int newlen = 0; -    if (textString != NULL) { -        selectedText->s = GetStringFromCFString(textString, &selectedText->len); -        selectedText->rectangular = isRectangular; -        // Default allocator releases both the CFString and the UniChar buffer (text) -        CFRelease( textString ); -        textString = NULL; -    } -    if (haveMatch || selectedText != NULL && selectedText->s != NULL) { -        return true; -    } -    return false; -} - -char *ScintillaMacOSX::GetStringFromCFString(CFStringRef &textString, int *textLen) -{ - -    // Allocate a buffer, plus the null byte -    CFIndex numUniChars = CFStringGetLength( textString ); -    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman); -    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 - -    // 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 -    *textLen = 0; -    char *result = Document::TransformLineEnds(textLen, -                                      cstring + bomLen, -                                      usedBufferLength - bomLen, -                                      pdoc->eolMode); -    delete[] cstring; -    return result; -} - -OSStatus ScintillaMacOSX::DragReceive(DragRef inDrag ) -{ -    // 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 ); - -    PasteboardRef pasteBoard; -    SelectionText selectedText; -    CFStringRef textString = NULL; -    bool isFileURL = false; -    if (!GetDragData(inDrag, pasteBoard, &selectedText, &isFileURL)) { -        return dragNotAcceptedErr; -    } - -    if (isFileURL) { -        NotifyURIDropped(selectedText.s); -    } else { -        // figure out if this is a move or a paste -        DragAttributes attributes; -        SInt16 modifiers = 0; -        GetDragAttributes( inDrag, &attributes ); -        bool moving = true; - -        SelectionPosition position = SPositionFromLocation(GetDragPoint(inDrag)); -        if ( attributes & kDragInsideSenderWindow ) { -            GetDragModifiers(inDrag, NULL, NULL, &modifiers); -            switch (modifiers & ~btnState)  // Filter out btnState (on for drop) -            { -            case optionKey: -                // default is copy text -                moving = false; -                break; -            case cmdKey: -            case cmdKey | optionKey: -            default: -                // what to do with these?  rectangular drag? -                break; -            } -        } - -        DropAt(position, selectedText.s, moving, selectedText.rectangular); -    } - -    return noErr; -} - -// Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070) -void ScintillaMacOSX::InsertCharacters (const UniChar* buf, int len) -{ -    CFStringRef str = CFStringCreateWithCharactersNoCopy (NULL, buf, (UInt32) len, kCFAllocatorNull); -    CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman); -    CFRange range = { 0, len }; -    CFIndex bufLen; -    CFStringGetBytes (str, range, encoding, '?', false, NULL, 0, &bufLen); -    UInt8* utf8buf = new UInt8 [bufLen]; -    CFStringGetBytes (str, range, encoding, '?', false, utf8buf, bufLen, NULL); -    AddCharUTF ((char*) utf8buf, bufLen, false); -    delete [] utf8buf; -    CFRelease (str); -} - -/** 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()) { -            // Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070) -            UniChar wcs[1] = { (UniChar) wParam}; -            InsertCharacters(wcs, 1); -            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) { -          // do a FULL paint. -          rcPaint = GetClientRectangle(); -          paintState = painting; -          paintingAllText = true; -          Paint(sw, rcPaint); -          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(); - -    // fixup mouse tracking regions, this causes mouseenter/exit to work -    if (HIViewGetSuperview(GetViewRef()) != NULL) { -        RgnHandle rgn = NewRgn(); -        HIRect r; -        HIViewGetFrame( reinterpret_cast<HIViewRef>( GetViewRef() ), &r ); -        SetRectRgn(rgn, short (r.origin.x), short (r.origin.y), -                  short (r.origin.x + r.size.width - (verticalScrollBarVisible ? scrollBarFixedSize : 0)), -                  short (r.origin.y + r.size.height - (showSBHorizontal ? scrollBarFixedSize : 0))); -        if (mouseTrackingRef == NULL) { -            CreateMouseTrackingRegion(GetOwner(), rgn, NULL, -                                        kMouseTrackingOptionsLocalClip, -                                        mouseTrackingID, NULL, -                                        GetControlEventTarget( GetViewRef() ), -                                        &mouseTrackingRef); -        } else { -            ChangeMouseTrackingRegion(mouseTrackingRef, rgn, NULL); -        } -        DisposeRgn(rgn); -    } else { -        if (mouseTrackingRef != NULL) { -            ReleaseMouseTrackingRegion(mouseTrackingRef); -        } -        mouseTrackingRef = NULL; -    } -} - -pascal void ScintillaMacOSX::LiveScrollHandler( HIViewRef control, SInt16 part ) -{ -    int currentValue = GetControl32BitValue( control ); -    int min = GetControl32BitMinimum( control ); -    int max = GetControl32BitMaximum( control ); -    int 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: -    case kControlNoPart: -        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) { -#ifdef EXT_INPUT -    ExtInput::activate (GetViewRef(), focus); -#endif -    if (NULL != notifyProc) -        notifyProc (notifyObj, WM_COMMAND, -                (uintptr_t) ((focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS) << 16), -                (uintptr_t) GetViewRef()); -} - -void ScintillaMacOSX::NotifyChange() { -    if (NULL != notifyProc) -        notifyProc (notifyObj, WM_COMMAND, -                (uintptr_t) (SCEN_CHANGE << 16), -                (uintptr_t) GetViewRef()); -} - -void ScintillaMacOSX::registerNotifyCallback(intptr_t windowid, SciNotifyFunc callback) { -    notifyObj = windowid; -    notifyProc = callback; -} - -void ScintillaMacOSX::NotifyParent(SCNotification scn) { -    if (NULL != notifyProc) { -        scn.nmhdr.hwndFrom = (void*) this; -        scn.nmhdr.idFrom = (unsigned int)wMain.GetID(); -        notifyProc (notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &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); -} - -#ifndef EXT_INPUT -// Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070) -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); -} -#endif - -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::ClearSelectionSimple }, -        { 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 ) -    { -#ifdef EXT_INPUT -        // We are getting a HI command, so stop extended input -        ExtInput::stop (scintilla->GetViewRef()); -#endif -        // 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 ( !sel.Empty() ); -} - -bool ScintillaMacOSX::CanUndo() -{ -    return pdoc->CanUndo(); -} - -bool ScintillaMacOSX::CanRedo() -{ -    return pdoc->CanRedo(); -} - -bool ScintillaMacOSX::AlwaysTrue() -{ -    return true; -} - -void ScintillaMacOSX::CopyToClipboard(const SelectionText &selectedText) { -    PasteboardRef theClipboard; -    SetPasteboardData(theClipboard, selectedText, false); // not in drag/drop -    // Done with the CFString -    CFRelease( theClipboard ); -} - -void ScintillaMacOSX::Copy() -{ -    if (!sel.Empty()) { -#ifdef EXT_INPUT -        ExtInput::stop (GetViewRef()); -#endif -        SelectionText selectedText; -        CopySelectionRange(&selectedText); -        fprintf(stderr, "copied text is rectangular? %d\n", selectedText.rectangular); -        CopyToClipboard(selectedText); -    } -} - -bool ScintillaMacOSX::CanPaste() -{ -    if (!Editor::CanPaste()) -        return false; - -    PasteboardRef theClipboard; -    bool isFileURL = false; - -    PasteboardCreate( kPasteboardClipboard, &theClipboard ); -    bool ok = GetPasteboardData(theClipboard, NULL, &isFileURL); -    CFRelease( theClipboard ); -    return ok; -} - -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 forceRectangular) -{ -    PasteboardRef theClipboard; -    SelectionText selectedText; -    selectedText.rectangular = forceRectangular; -    bool isFileURL = false; -    PasteboardCreate( kPasteboardClipboard, &theClipboard ); -    bool ok = GetPasteboardData(theClipboard, &selectedText, &isFileURL); -    CFRelease( theClipboard ); -    fprintf(stderr, "paste is rectangular? %d\n", selectedText.rectangular); -    if (!ok || !selectedText.s) -        // no data or no flavor we support -        return; - -    pdoc->BeginUndoAction(); -    ClearSelection(); -    if (selectedText.rectangular) { -        SelectionPosition selStart = sel.RangeMain().Start(); -        PasteRectangular(selStart, selectedText.s, selectedText.len); -    } else -    if ( pdoc->InsertString( sel.RangeMain().caret.Position(), selectedText.s, selectedText.len ) ) { -        SetEmptySelection( sel.RangeMain().caret.Position() + selectedText.len ); -    } - -    pdoc->EndUndoAction(); - -    Redraw(); -    EnsureCaretVisible(); -} - -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,  kCFStringEncodingUTF8 ); -    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; -#ifndef EXT_INPUT -    case kPageUpCharCode: -        return SCK_PRIOR; -    case kPageDownCharCode: -        return SCK_NEXT; -#endif -    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; -#ifdef EXT_INPUT -    // BP 2006-08-22: These codes below should not be translated. Otherwise TextInput() will fail for keys like SCK_ADD, which is '+'. -    case kBackspaceCharCode: -        return SCK_BACK; -    case kFunctionKeyCharCode: -    case kBellCharCode: -    case kVerticalTabCharCode: -    case kFormFeedCharCode: -    case 14: -    case 15: -    case kCommandCharCode: -    case kCheckCharCode: -    case kAppleLogoCharCode: -    case 21: -    case 22: -    case 23: -    case 24: -    case 25: -    case 26: -    case kEscapeCharCode: -        return 0; // ignore -    default: -        return unicodeChar; -#else -    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; -#endif -    } -} - -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); - -	if (uchrHandle) { -		// 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; -	} -	return 0; -} - -// 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 ); - -#ifdef EXT_INPUT -    UniChar* text = new UniChar [numUniChars]; -    err = event.GetParameter( kEventParamTextInputSendText, typeUnicodeText, actualSize, text ); -    PLATFORM_ASSERT( err == noErr ); - -    int modifiers = GetCurrentEventKeyModifiers(); - -    // Loop over all characters in sequence -    for (int i = 0; i < numUniChars; i++) -    { -        UniChar key = KeyTranslate( text[i] ); -        if (!key) -            continue; - -        bool consumed = false; - -        // need to go here first so e.g. Tab indentation works -        KeyDown ((int) key, (modifiers & shiftKey) != 0 || (modifiers & cmdKey) != 0, (modifiers & controlKey) != 0 || (modifiers & cmdKey) != 0, -                 (modifiers & optionKey) != 0 || (modifiers & cmdKey) != 0, &consumed); - -        // BP 2007-01-08: 1452623 Second Cmd+s to save doc inserts an "s" into the text on Mac. -        // At this point we need to ignore all cmd/option keys with char value smaller than 32 -        if( !consumed ) -            consumed = ( modifiers & ( cmdKey | optionKey ) ) != 0 && text[i] < 32; - -        // If not consumed, insert the original key -        if (!consumed) -            InsertCharacters (text+i, 1); -    } - -    delete[] text; -    return noErr; -#else -    // 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(sel.RangeMain().caret.Position(), buffer, usedBufferLength)) { -                SetEmptySelection(sel.RangeMain().caret.Position() + 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; -#endif -} - -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); -            ButtonMove( Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) ); -        } -        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 ); -    ::SetUserFocusWindow(::HIViewGetWindow( this->GetViewRef() )); -    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(); -} -} | 
