diff options
Diffstat (limited to 'macosx/ExtInput.cxx')
-rw-r--r-- | macosx/ExtInput.cxx | 608 |
1 files changed, 0 insertions, 608 deletions
diff --git a/macosx/ExtInput.cxx b/macosx/ExtInput.cxx deleted file mode 100644 index 677a82c3f..000000000 --- a/macosx/ExtInput.cxx +++ /dev/null @@ -1,608 +0,0 @@ -/******************************************************************************* - -Copyright (c) 2007 Adobe Systems Incorporated - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -********************************************************************************/ - -#include "ScintillaMacOSX.h" -#include "ExtInput.h" - -using namespace Scintilla; - -// uncomment this for a log to /dev/console -// #define LOG_TSM 1 - -#if LOG_TSM -FILE* logFile = NULL; -#endif - -static EventHandlerUPP tsmHandler; - -static EventTypeSpec tsmSpecs[] = { - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, -// { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputGetSelectedText } -}; - -#define kScintillaTSM 'ScTs' - -// The following structure is attached to the HIViewRef as property kScintillaTSM - -struct TSMData -{ - HIViewRef view; // this view - TSMDocumentID docid; // the TSM document ID - EventHandlerRef handler; // the event handler - ScintillaMacOSX* scintilla; // the Scintilla pointer - int styleMask; // the document style mask - int indicStyle [3]; // indicator styles save - int indicColor [3]; // indicator colors save - int selStart; // starting position of selection (Scintilla offset) - int selLength; // UTF-8 number of characters - int selCur; // current position (Scintilla offset) - int inhibitRecursion; // true to stop recursion - bool active; // true if this is active -}; - -static const int numSpecs = 5; - - -// Fetch a range of text as UTF-16; delete the buffer after use - -static char* getTextPortion (TSMData* data, UInt32 start, UInt32 size) -{ - Scintilla::TextRange range; - range.chrg.cpMin = start; - range.chrg.cpMax = start + size; - range.lpstrText = new char [size + 1]; - range.lpstrText [size] = 0; - data->scintilla->WndProc (SCI_GETTEXTRANGE, 0, (uptr_t) &range); - return range.lpstrText; -} - -static pascal OSStatus doHandleTSM (EventHandlerCallRef, EventRef inEvent, void* userData); - -void ExtInput::attach (HIViewRef viewRef) -{ - if (NULL == tsmHandler) - tsmHandler = NewEventHandlerUPP (doHandleTSM); - ::UseInputWindow (NULL, FALSE); - -#ifdef LOG_TSM - if (NULL == logFile) - logFile = fopen ("/dev/console", "a"); -#endif - - // create and attach the TSM data - TSMData* data = new TSMData; - - data->view = viewRef; - data->active = false; - data->inhibitRecursion = 0; - - ::GetControlProperty (viewRef, scintillaMacOSType, 0, sizeof( data->scintilla ), NULL, &data->scintilla); - - if (NULL != data->scintilla) - { - // create the TSM document ref - InterfaceTypeList interfaceTypes; - interfaceTypes[0] = kUnicodeDocumentInterfaceType; - ::NewTSMDocument (1, interfaceTypes, &data->docid, (long) viewRef); - // install my event handler - ::InstallControlEventHandler (viewRef, tsmHandler, numSpecs, tsmSpecs, data, &data->handler); - - ::SetControlProperty (viewRef, kScintillaTSM, 0, sizeof (data), &data); - } - else - delete data; -} - -static TSMData* getTSMData (HIViewRef viewRef) -{ - TSMData* data = NULL; - UInt32 n; - ::GetControlProperty (viewRef, kScintillaTSM, 0, sizeof (data), &n, (UInt32*) &data); - return data; -} - -void ExtInput::detach (HIViewRef viewRef) -{ - TSMData* data = getTSMData (viewRef); - if (NULL != data) - { - ::DeleteTSMDocument (data->docid); - ::RemoveEventHandler (data->handler); - delete data; - } -} - -void ExtInput::activate (HIViewRef viewRef, bool on) -{ - TSMData* data = getTSMData (viewRef); - if (NULL == data) - return; - - if (on) - { - ::ActivateTSMDocument (data->docid); - HIRect bounds; - ::HIViewGetBounds (viewRef, &bounds); - ::HIViewConvertRect (&bounds, viewRef, NULL); - RgnHandle hRgn = ::NewRgn(); - ::SetRectRgn (hRgn, (short) bounds.origin.x, (short) bounds.origin.y, - (short) (bounds.origin.x + bounds.size.width), - (short) (bounds.origin.y + bounds.size.height)); -#if LOG_TSM - fprintf (logFile, "TSMSetInlineInputRegion (%08lX, %ld:%ld-%ld:%ld)\n", - (long) data->docid, (long) bounds.origin.x, (long) bounds.origin.y, - (long) (bounds.origin.x + bounds.size.width), (long) (bounds.origin.y + bounds.size.height)); - fflush (logFile); -#endif - ::TSMSetInlineInputRegion (data->docid, HIViewGetWindow (data->view), hRgn); - ::DisposeRgn (hRgn); - ::UseInputWindow (NULL, FALSE); - } - else - { -#if LOG_TSM - fprintf (logFile, "DeactivateTSMDocument (%08lX)\n", (long) data->docid); - fflush (logFile); -#endif - ::DeactivateTSMDocument (data->docid); - } -} - -static void startInput (TSMData* data, bool delSelection = true) -{ - if (!data->active && 0 == data->inhibitRecursion) - { - data->active = true; - - // Delete any selection - if( delSelection ) - data->scintilla->WndProc (SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>("")); - - // need all style bits because we do indicators - data->styleMask = data->scintilla->WndProc (SCI_GETSTYLEBITS, 0, 0); - data->scintilla->WndProc (SCI_SETSTYLEBITS, 5, 0); - - // Set the target range for successive replacements - data->selStart = - data->selCur = data->scintilla->WndProc (SCI_GETCURRENTPOS, 0, 0); - data->selLength = 0; - - // save needed styles - for (int i = 0; i < 2; i++) - { - data->indicStyle [i] = data->scintilla->WndProc (SCI_INDICGETSTYLE, i, 0); - data->indicColor [i] = data->scintilla->WndProc (SCI_INDICGETFORE, i, 0); - } - // set styles and colors - data->scintilla->WndProc (SCI_INDICSETSTYLE, 0, INDIC_SQUIGGLE); - data->scintilla->WndProc (SCI_INDICSETFORE, 0, 0x808080); - data->scintilla->WndProc (SCI_INDICSETSTYLE, 1, INDIC_PLAIN); // selected converted - data->scintilla->WndProc (SCI_INDICSETFORE, 1, 0x808080); - data->scintilla->WndProc (SCI_INDICSETSTYLE, 2, INDIC_PLAIN); // selected raw - data->scintilla->WndProc (SCI_INDICSETFORE, 2, 0x0000FF); - // stop Undo - data->scintilla->WndProc (SCI_BEGINUNDOACTION, 0, 0); - } -} - -static void stopInput (TSMData* data, int pos) -{ - if (data->active && 0 == data->inhibitRecursion) - { - // First fix the doc - this may cause more messages - // but do not fall into recursion - data->inhibitRecursion++; - ::FixTSMDocument (data->docid); - data->inhibitRecursion--; - data->active = false; - - // Remove indicator styles - data->scintilla->WndProc (SCI_STARTSTYLING, data->selStart, INDICS_MASK); - data->scintilla->WndProc (SCI_SETSTYLING, pos - data->selStart, 0); - // Restore old indicator styles and colors - data->scintilla->WndProc (SCI_SETSTYLEBITS, data->styleMask, 0); - for (int i = 0; i < 2; i++) - { - data->scintilla->WndProc (SCI_INDICSETSTYLE, i, data->indicStyle [i]); - data->scintilla->WndProc (SCI_INDICSETFORE, i, data->indicColor [i]); - } - - // remove selection and re-allow selections to display - data->scintilla->WndProc (SCI_SETSEL, pos, pos); - data->scintilla->WndProc (SCI_TARGETFROMSELECTION, 0, 0); - data->scintilla->WndProc (SCI_HIDESELECTION, 0, 0); - - // move the caret behind the current area - data->scintilla->WndProc (SCI_SETCURRENTPOS, pos, 0); - // re-enable Undo - data->scintilla->WndProc (SCI_ENDUNDOACTION, 0, 0); - // re-colorize - int32_t startLine = data->scintilla->WndProc (SCI_LINEFROMPOSITION, data->selStart, 0); - int32_t startPos = data->scintilla->WndProc (SCI_POSITIONFROMLINE, startLine, 0); - int32_t endLine = data->scintilla->WndProc (SCI_LINEFROMPOSITION, pos, 0); - if (endLine == startLine) - endLine++; - int32_t endPos = data->scintilla->WndProc (SCI_POSITIONFROMLINE, endLine, 0); - - data->scintilla->WndProc (SCI_COLOURISE, startPos, endPos); - } -} - -void ExtInput::stop (HIViewRef viewRef) -{ - TSMData* data = getTSMData (viewRef); - if (NULL != data) - stopInput (data, data->selStart + data->selLength); -} - -static char* UTF16toUTF8 (const UniChar* buf, int len, int& utf8len) -{ - CFStringRef str = CFStringCreateWithCharactersNoCopy (NULL, buf, (UInt32) len, kCFAllocatorNull); - CFRange range = { 0, len }; - CFIndex bufLen; - CFStringGetBytes (str, range, kCFStringEncodingUTF8, '?', false, NULL, 0, &bufLen); - UInt8* utf8buf = new UInt8 [bufLen+1]; - CFStringGetBytes (str, range, kCFStringEncodingUTF8, '?', false, utf8buf, bufLen, NULL); - utf8buf [bufLen] = 0; - CFRelease (str); - utf8len = (int) bufLen; - return (char*) utf8buf; -} - -static int UCS2Length (const char* buf, int len) -{ - int n = 0; - while (len > 0) - { - int bytes = 0; - char ch = *buf; - while (ch & 0x80) - bytes++, ch <<= 1; - len -= bytes; - n += bytes; - } - return n; -} - -static int UTF8Length (const UniChar* buf, int len) -{ - int n = 0; - while (len > 0) - { - UInt32 uch = *buf++; - len--; - if (uch >= 0xD800 && uch <= 0xDBFF && len > 0) - { - UInt32 uch2 = *buf; - if (uch2 >= 0xDC00 && uch2 <= 0xDFFF) - { - buf++; - len--; - uch = ((uch & 0x3FF) << 10) + (uch2 & 0x3FF); - } - } - n++; - if (uch > 0x7F) - n++; - if (uch > 0x7FF) - n++; - if (uch > 0xFFFF) - n++; - if (uch > 0x1FFFFF) - n++; - if (uch > 0x3FFFFFF) - n++; - } - return n; -} - -static OSStatus handleTSMUpdateActiveInputArea (TSMData* data, EventRef inEvent) -{ - UInt32 fixLength; - int caretPos = -1; - UInt32 actualSize; - ::TextRangeArray* hiliteRanges = NULL; - char* hiliteBuffer = NULL; - bool done; - - // extract the text - UniChar* buffer = NULL; - UniChar temp [128]; - UniChar* text = temp; - - // get the fix length (in bytes) - OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendFixLen, - typeLongInteger, NULL, sizeof (long), NULL, &fixLength); - // need the size (in bytes) - if (noErr == err) - err = ::GetEventParameter (inEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, 256, &actualSize, temp); - - // then allocate and fetch if necessary - UInt32 textLength = actualSize / sizeof (UniChar); - fixLength /= sizeof (UniChar); - - if (noErr == err) - { - // this indicates that we are completely done - done = (fixLength == textLength || fixLength < 0); - if (textLength >= 128) - { - buffer = text = new UniChar [textLength]; - err = ::GetEventParameter (inEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, actualSize, NULL, (void*) text); - } - - // set the text now, but convert it to UTF-8 first - int utf8len; - char* utf8 = UTF16toUTF8 (text, textLength, utf8len); - data->scintilla->WndProc (SCI_SETTARGETSTART, data->selStart, 0); - data->scintilla->WndProc (SCI_SETTARGETEND, data->selStart + data->selLength, 0); - data->scintilla->WndProc (SCI_HIDESELECTION, 1, 0); - data->scintilla->WndProc (SCI_REPLACETARGET, utf8len, (sptr_t) utf8); - data->selLength = utf8len; - delete [] utf8; - } - - // attempt to extract the array of hilite ranges - if (noErr == err) - { - ::TextRangeArray tempTextRangeArray; - OSStatus tempErr = ::GetEventParameter (inEvent, kEventParamTextInputSendHiliteRng, - typeTextRangeArray, NULL, sizeof (::TextRangeArray), &actualSize, &tempTextRangeArray); - if (noErr == tempErr) - { - // allocate memory and get the stuff! - hiliteBuffer = new char [actualSize]; - hiliteRanges = (::TextRangeArray*) hiliteBuffer; - err = ::GetEventParameter (inEvent, kEventParamTextInputSendHiliteRng, - typeTextRangeArray, NULL, actualSize, NULL, hiliteRanges); - if (noErr != err) - { - delete [] hiliteBuffer; - hiliteBuffer = NULL; - hiliteRanges = NULL; - } - } - } -#if LOG_TSM - fprintf (logFile, "kEventTextInputUpdateActiveInputArea:\n" - " TextLength = %ld\n" - " FixLength = %ld\n", - (long) textLength, (long) fixLength); - fflush (logFile); -#endif - - if (NULL != hiliteRanges) - { - for (int i = 0; i < hiliteRanges->fNumOfRanges; i++) - { -#if LOG_TSM - fprintf (logFile, " Range #%d: %ld-%ld (%d)\n", - i+1, - hiliteRanges->fRange[i].fStart, - hiliteRanges->fRange[i].fEnd, - hiliteRanges->fRange[i].fHiliteStyle); - fflush (logFile); -#endif - // start and end of range, zero based - long bgn = long (hiliteRanges->fRange[i].fStart) / sizeof (UniChar); - long end = long (hiliteRanges->fRange[i].fEnd) / sizeof (UniChar); - if (bgn >= 0 && end >= 0) - { - // move the caret if this is requested - if (hiliteRanges->fRange[i].fHiliteStyle == kTSMHiliteCaretPosition) - caretPos = bgn; - else - { - // determine which style to use - int style; - switch (hiliteRanges->fRange[i].fHiliteStyle) - { - case kTSMHiliteRawText: style = INDIC0_MASK; break; - case kTSMHiliteSelectedRawText: style = INDIC0_MASK; break; - case kTSMHiliteConvertedText: style = INDIC1_MASK; break; - case kTSMHiliteSelectedConvertedText: style = INDIC2_MASK; break; - default: style = INDIC0_MASK; - } - // bgn and end are Unicode offsets from the starting pos - // use the text buffer to determine the UTF-8 offsets - long utf8bgn = data->selStart + UTF8Length (text, bgn); - long utf8size = UTF8Length (text + bgn, end - bgn); - // set indicators - int oldEnd = data->scintilla->WndProc (SCI_GETENDSTYLED, 0, 0); - data->scintilla->WndProc (SCI_STARTSTYLING, utf8bgn, INDICS_MASK); - data->scintilla->WndProc (SCI_SETSTYLING, utf8size, style & ~1); - data->scintilla->WndProc (SCI_STARTSTYLING, oldEnd, 31); - } - } - } - } - if (noErr == err) - { - // if the fixed length is == to the new text, we are done - if (done) - stopInput (data, data->selStart + UTF8Length (text, textLength)); - else if (caretPos >= 0) - { - data->selCur = data->selStart + UTF8Length (text, caretPos); - data->scintilla->WndProc (SCI_SETCURRENTPOS, data->selCur, 0); - } - } - - delete [] hiliteBuffer; - delete [] buffer; - return err; -} - -struct MacPoint { - short v; - short h; -}; - -static OSErr handleTSMOffset2Pos (TSMData* data, EventRef inEvent) -{ - long offset; - - // get the offfset to convert - OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendTextOffset, - typeLongInteger, NULL, sizeof (long), NULL, &offset); - if (noErr == err) - { - // where is the caret now? - HIPoint where; - - int line = (int) data->scintilla->WndProc (SCI_LINEFROMPOSITION, data->selCur, 0); - where.x = data->scintilla->WndProc (SCI_POINTXFROMPOSITION, 0, data->selCur); - where.y = data->scintilla->WndProc (SCI_POINTYFROMPOSITION, 0, data->selCur) - + data->scintilla->WndProc (SCI_TEXTHEIGHT, line, 0); - // convert to window coords - ::HIViewConvertPoint (&where, data->view, NULL); - // convert to screen coords - Rect global; - GetWindowBounds (HIViewGetWindow (data->view), kWindowStructureRgn, &global); - MacPoint pt; - pt.h = (short) where.x + global.left; - pt.v = (short) where.y + global.top; - - // set the result - err = ::SetEventParameter (inEvent, kEventParamTextInputReplyPoint, typeQDPoint, sizeof (MacPoint), &pt); -#if LOG_TSM - fprintf (logFile, "kEventTextInputOffsetToPos:\n" - " Offset: %ld\n" - " Pos: %ld:%ld (orig = %ld:%ld)\n", offset, - (long) pt.h, (long) pt.v, - (long) where.x, (long) where.y); - fflush (logFile); -#endif - } - return err; -} - -static OSErr handleTSMPos2Offset (TSMData* data, EventRef inEvent) -{ - MacPoint qdPosition; - long offset; - short regionClass; - - // retrieve the global point to convert - OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendCurrentPoint, - typeQDPoint, NULL, sizeof (MacPoint), NULL, &qdPosition); - if (noErr == err) - { -#if LOG_TSM - fprintf (logFile, "kEventTextInputPosToOffset:\n" - " Pos: %ld:%ld\n", (long) qdPosition.v, (long) qdPosition.h); - fflush (logFile); -#endif - // convert to local coordinates - HIRect rect; - rect.origin.x = qdPosition.h; - rect.origin.y = qdPosition.v; - rect.size.width = - rect.size.height = 1; - ::HIViewConvertRect (&rect, NULL, data->view); - - // we always report the position to be within the composition; - // coords inside the same pane are clipped to the composition, - // and if the position is outside, then we deactivate this instance - // this leaves the edit open and active so we can edit multiple panes - regionClass = kTSMInsideOfActiveInputArea; - - // compute the offset (relative value) - offset = data->scintilla->WndProc (SCI_POSITIONFROMPOINTCLOSE, (uptr_t) rect.origin.x, (sptr_t) rect.origin.y); - if (offset >= 0) - { - // convert to a UTF-16 offset (Brute Force) - char* buf = getTextPortion (data, 0, offset); - offset = UCS2Length (buf, offset); - delete [] buf; - -#if LOG_TSM - fprintf (logFile, " Offset: %ld (class %ld)\n", offset, (long) regionClass); - fflush (logFile); -#endif - // store the offset - err = ::SetEventParameter (inEvent, kEventParamTextInputReplyTextOffset, typeLongInteger, sizeof (long), &offset); - if (noErr == err) - err = ::SetEventParameter (inEvent, kEventParamTextInputReplyRegionClass, typeShortInteger, sizeof (short), ®ionClass); - } - else - { - // not this pane! - err = eventNotHandledErr; - ExtInput::activate (data->view, false); - } - - } - return err; -} - -static OSErr handleTSMGetText (TSMData* data, EventRef inEvent) -{ - char* buf = getTextPortion (data, data->selStart, data->selLength); - -#if LOG_TSM - fprintf (logFile, "kEventTextInputGetSelectedText:\n" - " Text: \"%s\"\n", buf); - fflush (logFile); -#endif - OSStatus status = ::SetEventParameter (inEvent, kEventParamTextInputReplyText, typeUTF8Text, data->selLength, buf); - delete [] buf; - return status; -} - -static pascal OSStatus doHandleTSM (EventHandlerCallRef, EventRef inEvent, void* userData) -{ - TSMData* data = (TSMData*) userData; - - OSStatus err = eventNotHandledErr; - - switch (::GetEventKind (inEvent)) - { - case kEventTextInputUpdateActiveInputArea: - // Make sure that input has been started - startInput (data); - err = handleTSMUpdateActiveInputArea (data, inEvent); - break; -// case kEventTextInputUnicodeForKeyEvent: -// err = handleTSMUnicodeInput (inEvent); -// break; - case kEventTextInputOffsetToPos: - err = handleTSMOffset2Pos (data, inEvent); - break; - case kEventTextInputPosToOffset: - err = handleTSMPos2Offset (data, inEvent); - break; - case kEventTextInputGetSelectedText: - // Make sure that input has been started - startInput (data, false); - err = handleTSMGetText (data, inEvent); - break; - } - return err; -} - |