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; -} - | 
