aboutsummaryrefslogtreecommitdiffhomepage
path: root/macosx/ExtInput.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/ExtInput.cxx')
-rw-r--r--macosx/ExtInput.cxx608
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), &regionClass);
- }
- 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;
-}
-