diff options
author | mixedpuppy <unknown> | 2007-12-05 23:06:58 +0000 |
---|---|---|
committer | mixedpuppy <unknown> | 2007-12-05 23:06:58 +0000 |
commit | 21f54a4c47ad89ab870be19b4db5ca1914992608 (patch) | |
tree | 7a56a2c74170e09c85b98ecdeebce310d001ad7d /macosx/ScintillaMacOSX.cxx | |
parent | edac7fdf643fc5f1a374508f4f993de0951ff324 (diff) | |
download | scintilla-mirror-21f54a4c47ad89ab870be19b4db5ca1914992608.tar.gz |
modified version of adobe OSX patches. Most of these patches are provided by Adobe, though I've
reorganized a lot of them
- improved drag/drop
- make copy/paste use modern pasteboard api's
- optimized textlayout usage
- reduce assertions for debug builds
- implement IME support
- other minor things
patches are available in openkomodo, which is a good test ground for scintilla osx (until someone
ports SCiTE).
Diffstat (limited to 'macosx/ScintillaMacOSX.cxx')
-rw-r--r-- | macosx/ScintillaMacOSX.cxx | 837 |
1 files changed, 479 insertions, 358 deletions
diff --git a/macosx/ScintillaMacOSX.cxx b/macosx/ScintillaMacOSX.cxx index 9ac746f4b..410d105d9 100644 --- a/macosx/ScintillaMacOSX.cxx +++ b/macosx/ScintillaMacOSX.cxx @@ -6,7 +6,12 @@ #include "ScintillaMacOSX.h" +#ifdef EXT_INPUT +// External Input Editor +#include "ExtInput.h" +#else #include "UniConversion.h" +#endif using namespace Scintilla; @@ -59,9 +64,103 @@ static int BOMlen(unsigned char *cstr) { 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 ); @@ -123,7 +222,13 @@ ScintillaMacOSX::ScintillaMacOSX( void* windowid ) : GetEventTypeCount( commandEventInfo ), commandEventInfo, this, NULL); - assert( err == noErr ); +#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() { @@ -134,6 +239,9 @@ ScintillaMacOSX::~ScintillaMacOSX() { } mouseTrackingRef = NULL; SetTicking(false); +#ifdef EXT_INPUT + ExtInput::detach (GetViewRef()); +#endif } void ScintillaMacOSX::Initialise() { @@ -226,43 +334,12 @@ HIPoint ScintillaMacOSX::GetLocalPoint(::Point pt) } 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 selStart = SelectionStart(); + int selEnd = SelectionEnd(); int startLine = pdoc->LineFromPosition(selStart); int endLine = pdoc->LineFromPosition(selEnd); Point pt; @@ -318,7 +395,7 @@ void ScintillaMacOSX::StartDrag() { client = GetClientRectangle(); paintState = painting; sw->InitPixMap( client.Width(), client.Height(), NULL, NULL ); - + paintingAllText = true; Paint(sw, imageRect); paintState = notPainting; @@ -354,28 +431,12 @@ void ScintillaMacOSX::StartDrag() { RectRgn(dragRegion, &rcSel); -#ifdef DRAG_DROP_PASTEBOARD + SelectionText selectedText; + CopySelectionRange(&selectedText); 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); + SetPasteboardData(theClipboard, selectedText); 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 + CFRelease( theClipboard ); // Set the item's bounding rectangle in global coordinates. SetDragItemBounds(inDrag, 1, &rcSel); @@ -394,9 +455,9 @@ void ScintillaMacOSX::StartDrag() { } // Drag the text. TrackDrag will return userCanceledErr if the drop whooshed back for any reason. - inDragSession = true; + inDragDrop = ddDragging; OSErr error = TrackDrag(inDrag, &mouseDownEvent, dragRegion); - inDragSession = false; + 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 @@ -424,23 +485,12 @@ void ScintillaMacOSX::StartDrag() { // 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) @@ -504,8 +554,7 @@ Scintilla::Point ScintillaMacOSX::GetDragPoint(DragRef inDrag) { ::Point mouse, globalMouse; GetDragMouse(inDrag, &mouse, &globalMouse); - QDGlobalToLocalPoint(GetWindowPort(GetOwner()), &globalMouse); - HIPoint hiPoint = {globalMouse.h, globalMouse.v}; + HIPoint hiPoint = GetLocalPoint (globalMouse); return Point(static_cast<int>(hiPoint.x), static_cast<int>(hiPoint.y)); } @@ -548,22 +597,13 @@ void ScintillaMacOSX::DragScroll() 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 )) { + bool isFileURL = false; + if (!GetDragData(inDrag, pasteBoard, NULL, &isFileURL)) { return false; } - SetDragPosition(PositionFromLocation(Point(static_cast<int>(globalHit.x),static_cast<int>(globalHit.y)))); + Point pt = GetDragPoint (inDrag); + SetDragPosition(PositionFromLocation(pt)); SetDragCursor(inDrag); return true; @@ -577,21 +617,84 @@ bool ScintillaMacOSX::DragLeave(DragRef inDrag ) return true; } -OSStatus ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, CFStringRef *textString) +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 dragNotAcceptedErr; + return false; + } + return GetPasteboardData(pasteBoard, selectedText, isFileURL); +} + +void ScintillaMacOSX::SetPasteboardData(PasteboardRef &theClipboard, const SelectionText &selectedText) +{ + 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( 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; - status = PasteboardGetItemCount(pasteBoard, &itemCount); + OSStatus status = PasteboardGetItemCount(pasteBoard, &itemCount); if (status != noErr) { - return dragNotAcceptedErr; + 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 @@ -604,13 +707,13 @@ OSStatus ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, status = PasteboardGetItemIdentifier(pasteBoard, i, &itemID); if (status != noErr) { - return dragNotAcceptedErr; + return false; } // how many flavors in this item? status = PasteboardCopyItemFlavors(pasteBoard, itemID, &flavorTypeArray); if (status != noErr) { - return dragNotAcceptedErr; + return false; } if (flavorTypeArray != NULL) @@ -621,57 +724,83 @@ OSStatus ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard, { CFDataRef flavorData; CFStringRef flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, j); - if (flavorType != NULL) { - if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))) // this is 'utxt' + 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) { - // 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 dataSize = CFDataGetLength (flavorData); + const UInt8* dataBytes = CFDataGetBytePtr (flavorData); + switch (format) { - CFIndex flavorDataSize = CFDataGetLength(flavorData); - - // getting the text - *textString = CFStringCreateWithCharacters(NULL, - (UniChar *)CFDataGetBytePtr(flavorData), - flavorDataSize >> 1); - CFRelease(flavorData); - goto DragDataRetrieved; + 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; } } } } -DragDataRetrieved: +PasteboardDataRetrieved: 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; + 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; } - - // getting the length of the text and setting the value - if (textString == NULL) { - return noErr; + if (haveMatch || selectedText != NULL && selectedText->s != NULL) { + return true; } + return false; +} - // XXX the following is identical (ALMOST) to code in Paste +char *ScintillaMacOSX::GetStringFromCFString(CFStringRef &textString, int *textLen) +{ // Allocate a buffer, plus the null byte CFIndex numUniChars = CFStringGetLength( textString ); - CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII); + CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman); CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1; char* cstring = new char[maximumByteLength]; CFIndex usedBufferLength = 0; @@ -680,84 +809,84 @@ OSStatus ScintillaMacOSX::DragReceive(DragRef inDrag ) '?', 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(); + *textLen = 0; + char *result = Document::TransformLineEnds(textLen, + cstring + bomLen, + usedBufferLength - bomLen, + pdoc->eolMode); + delete[] cstring; + return result; +} - // figure out if this is a move or a paste - DragAttributes attributes; - SInt16 modifiers = 0; - GetDragAttributes( inDrag, &attributes ); +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 ); - 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; - } + PasteboardRef pasteBoard; + SelectionText selectedText; + CFStringRef textString = NULL; + bool isFileURL = false; + if (!GetDragData(inDrag, pasteBoard, &selectedText, &isFileURL)) { + return dragNotAcceptedErr; + } + + if (isFileURL) { + NotifyURIDropped(selectedText.s); } else { - if (position >= selStart && position <= selEnd) { - // droping on top of a selection from another app or control, clear it - position = selStart; - ClearSelection(); + // figure out if this is a move or a paste + DragAttributes attributes; + SInt16 modifiers = 0; + GetDragAttributes( inDrag, &attributes ); + bool moving = true; + + int position = PositionFromLocation(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; + } } - } - // lets put the text in our document now - if ( pdoc->InsertString( position, droppedText, droppedLen ) ) - { - SetEmptySelection( currentPos + droppedLen ); + DropAt(position, selectedText.s, moving, selectedText.rectangular); } -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; } +// 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) { @@ -774,11 +903,9 @@ sptr_t ScintillaMacOSX::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPa 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); + // Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070) + UniChar wcs[1] = { (UniChar) wParam}; + InsertCharacters(wcs, 1); return 1; } else { return 0; @@ -892,11 +1019,11 @@ void ScintillaMacOSX::SyncPaint(void* gc, PRectangle rc) { sw->Init( gc, wMain.GetID() ); Paint(sw, rc); if (paintState == paintAbandoned) { - // XXX a bit of a hack to avoid excesive flashing when typing. + // do a FULL paint. + rcPaint = GetClientRectangle(); paintState = painting; paintingAllText = true; - Paint(sw, rc); - // TODO: There is a chance that this causes an infinite drawing loop... + Paint(sw, rcPaint); wMain.InvalidateAll(); } sw->Release(); @@ -1004,18 +1131,39 @@ void ScintillaMacOSX::Resize(int width, int height) { } ChangeSize(); -} -void ScintillaMacOSX::NotifyChange() { - // TODO: How should this be implemented on OS X? Should it be? + // 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 ) { - SInt16 currentValue = GetControl32BitValue( control ); - SInt16 min = GetControl32BitMinimum( control ); - SInt16 max = GetControl32BitMaximum( control ); - SInt16 page = GetControlViewSize( control ); + 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; @@ -1066,6 +1214,7 @@ pascal void ScintillaMacOSX::LiveScrollHandler( HIViewRef control, SInt16 part ) break; case kControlIndicatorPart: + case kControlNoPart: newValue = currentValue; break; @@ -1139,30 +1288,34 @@ bool ScintillaMacOSX::ScrollBarHit(HIPoint location) { return false; } - -void ScintillaMacOSX::NotifyFocus(bool /*focus*/) { - // TODO: How should this be implemented on OS X? Should it be? +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()); } -typedef void (*SciNotifyFunc)(sptr_t *, long); -void ScintillaMacOSX::NotifyParent(SCNotification scn) { - OSStatus err; - sptr_t *ptr = NULL; - SciNotifyFunc fn = NULL; +void ScintillaMacOSX::NotifyChange() { + if (NULL != notifyProc) + notifyProc (notifyObj, WM_COMMAND, + (uintptr_t) (SCEN_CHANGE << 16), + (uintptr_t) GetViewRef()); +} - // 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; +void ScintillaMacOSX::registerNotifyCallback(intptr_t windowid, SciNotifyFunc callback) { + notifyObj = windowid; + notifyProc = callback; +} - scn.nmhdr.hwndFrom = GetViewRef(); - scn.nmhdr.idFrom = (unsigned int)wMain.GetID(); - fn(ptr, (long int)&scn); +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) { @@ -1182,6 +1335,8 @@ void ScintillaMacOSX::NotifyURIDropped(const char *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); @@ -1193,6 +1348,7 @@ int ScintillaMacOSX::KeyDefault(int key, int modifiers) { } //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers); } +#endif template <class T, class U> struct StupidMap @@ -1254,6 +1410,10 @@ pascal OSStatus ScintillaMacOSX::CommandEventHandler( EventHandlerCallRef /*inCa 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 ); @@ -1316,60 +1476,37 @@ bool ScintillaMacOSX::AlwaysTrue() } 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 ); - + PasteboardRef theClipboard; + SetPasteboardData(theClipboard, selectedText); // 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; + CFRelease( theClipboard ); } void ScintillaMacOSX::Copy() { if (currentPos != anchor) { +#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() { - ScrapRef scrap = NULL; - OSStatus err; - err = GetCurrentScrap( &scrap ); - assert( err == noErr && scrap != NULL ); + if (!Editor::CanPaste()) + return false; + + PasteboardRef theClipboard; + bool isFileURL = false; - ScrapFlavorFlags flavorFlags; - return GetScrapFlavorFlags ( scrap, kScrapFlavorTypeUnicode, &flavorFlags ) == noErr || - GetScrapFlavorFlags ( scrap, kScrapFlavorTypeText, &flavorFlags ) == noErr; + PasteboardCreate( kPasteboardClipboard, &theClipboard ); + bool ok = GetPasteboardData(theClipboard, NULL, &isFileURL); + CFRelease( theClipboard ); + return ok; } void ScintillaMacOSX::Paste() @@ -1380,112 +1517,34 @@ void ScintillaMacOSX::Paste() // 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) +void ScintillaMacOSX::Paste(bool forceRectangular) { - // 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 + 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; - } - - - // 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) { + if (selectedText.rectangular) { int selStart = SelectionStart(); - PasteRectangular(selStart, pasted, newlen); + PasteRectangular(selStart, selectedText.s, selectedText.len); } else - if ( pdoc->InsertString( currentPos, pasted, newlen ) ) { - SetEmptySelection( currentPos + newlen ); + if ( pdoc->InsertString( currentPos, selectedText.s, selectedText.len ) ) { + SetEmptySelection( currentPos + selectedText.len ); } - delete[] pasted; - delete[] cstring; - cstring = NULL; - pdoc->EndUndoAction(); - NotifyChange(); + Redraw(); + EnsureCaretVisible(); } void ScintillaMacOSX::CreateCallTipWindow(PRectangle rc) { @@ -1602,7 +1661,7 @@ void ScintillaMacOSX::AddToPopUp( const char *label, int cmd, bool enabled ) return; } - CFStringRef string = CFStringCreateWithCString( NULL, label, kTextEncodingMacRoman ); + CFStringRef string = CFStringCreateWithCString( NULL, label, kCFStringEncodingUTF8 ); OSStatus err; err = AppendMenuItemTextWithCFString( reinterpret_cast<MenuRef>( popup.GetID() ), string, attributes, macCommand, NULL ); @@ -1702,10 +1761,12 @@ static inline int KeyTranslate( UniChar unicodeChar ) 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 @@ -1714,6 +1775,30 @@ static inline int KeyTranslate( UniChar unicodeChar ) 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: @@ -1730,6 +1815,7 @@ static inline int KeyTranslate( UniChar unicodeChar ) return kFunctionKeyCharCode; default: return 0; +#endif } } @@ -1775,6 +1861,39 @@ OSStatus ScintillaMacOSX::TextInput( TCarbonEvent& event ) 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 ); @@ -1873,6 +1992,7 @@ OSStatus ScintillaMacOSX::TextInput( TCarbonEvent& event ) string = NULL; return err; +#endif } UInt32 ScintillaMacOSX::GetBehaviors() @@ -1891,6 +2011,7 @@ OSStatus ScintillaMacOSX::MouseEntered(HIPoint& location, UInt32 /*inKeyModifier } 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; } @@ -1945,7 +2066,7 @@ OSStatus ScintillaMacOSX::MouseDown( HIPoint& location, UInt32 modifiers, EventM #if !defined(CONTAINER_HANDLES_EVENTS) OSStatus err; err = SetKeyboardFocus( this->GetOwner(), this->GetViewRef(), 1 ); - assert( err == noErr ); + ::SetUserFocusWindow(::HIViewGetWindow( this->GetViewRef() )); return noErr; #else return eventNotHandledErr; // allow event to go to container |