| < Previous PageHelp IndexNext Page > |
Spell Catcher X has some powerful tools available for developers to test certain aspects of their application's text input (TSM or NSTextInput) support. There are some defaults (described below) that can be set to enable features such as inline input and TSM Document Access, useful for testing and debugging purposes.
There is a default that can be set to show a TSM Tests submenu in the input menu. This submenu currently has two commands:
To show the TSM Tests submenu (in the Terminal, type):
defaults write com.rainmaker.SpellCatcher SCEnableTSMTestsMenu -bool TRUE
To hide the TSM Tests submenu:
defaults write com.rainmaker.SpellCatcher SCEnableTSMTestsMenu -bool FALSE
Spell Catcher X’s input method does not use inline input (strictly speaking, doesn’t maintain an active inline input area - although it does send UpdateActiveInputArea events for many purposes). When the Inline Input menu item is selected, Spell Catcher’s input method will allow traditional inline input. Note that when in this mode, none of the actual machinery is hooked up. In other words, no spell checking, no completion, no interactive features at all are available (something for the future).
Notes: Spell Catcher’s inline input implementation should allow the following functionality, given a reasonably complete UAIA implementation in the underlying application:
Spell Catcher’s input method currently takes advantage of some TSM document access events (kEventClassTSMDocumentAccess) if the application you are using it with supports it. Specifically, it uses the following events to determine the currently-selected text:
kEventTSMDocumentAccessGetLength
kEventTSMDocumentAccessGetSelectedRange
kEventTSMDocumentAccessGetCharactersPtr
kEventTSMDocumentAccessGetCharactersPtrForLargestBuffer
kEventTSMDocumentAccessGetCharacters
The following TSM document access events are used to implement the “Make replacements directly (without backspacing) where possible” feature (Spell Catcher Preferences, Interactive pane, Typing tab):
kEventTextInputUpdateActiveInputArea with the kEventParamTextInputSendReplaceRange parameter
kEventTSMDocumentAccessLockDocument
kEventTSMDocumentAccessUnlockDocument
The Document Access command also uses the above events, along with the following in order to get information about the fonts used in a given range of the document’s text:
kEventTSMDocumentAccessGetFont, requires that the kEventParamTSMDocAccessRequestedCharacterAttributes parameter is supported for kTSMDocAccessFontSizeAttributeBit and kTSMDocAccessEffectiveRangeAttributeBit
kEventTSMDocumentAccessGetGlyphInfo, requires that the kEventParamTSMDocAccessRequestedCharacterAttributes parameter is supported for kTSMDocAccessEffectiveRangeAttributeBit
The following text input events (kEventClassTextInput) are also used extensively:
kEventTextInputOffsetToPos, requires that the application properly handles non-zero (positive and negative) offsets in the absence of an active inline input area
kEventTextInputPosToOffset
In a nutshell, the Document Access command gets as much information it can about the document’s text, then (optionally, for testing purposes) checks it for errors, and renders it in an overlay window, using the information obtained from the app from the above events, directly overlapping the corresponding text in the document (ideally).
To track changes to the document window’s size, position, and contents, if accessibility is turned on (System Preferences, Universal Access, “Enable access for assistive devices”), various AX notifications are observed to keep what’s drawn in the overlay window in sync with what you see onscreen. Additionally, accessibility APIs are used (if available) to potentially get a more accurate representation of the document’s text and its position on the screen.
Each word drawn in the overlay shows a help tag with the info obtained from TSM and accessibility whenever you hover the mouse over it.
As of this writing, the only text editing view available in Mac OS X that does a reasonable job of supporting the above is Cocoa’s NSTextView. Many Cocoa applications use NSTextView for all of their text editing needs. Some Cocoa applications subclass NSTextView in a way that breaks some of this support. Other applications may use some other text view (Apple’s Mail app on Tiger and Dashboard widgets use editable WebView, Pages and Keynote use a private-to-iWork view) that doesn’t support TSM doc access at all, or has buggy support. Carbon’s MLTE almost works, but due to a long-standing bug in its kEventTextInputOffsetToPos handler when given a negative offset, only shows text after the insertion point. It’s quickly apparent how well an application supports TSM document access after using this feature for just a couple of minutes!
To see how things (mostly) should work with the Document Access command, we recommend good old TextEdit. Best to turn on accessibility as well. Open a TextEdit document, modify it so that it contains some spelling (or other) errors that Spell Catcher can detect. Introduce a number of font, style, size and other typography changes to get an idea of how they are handled. Choose the Document Access command to show the overlay and palette, start playing.
There are a few experimental features at this point:
While the current implementation is adequate for testing purposes, it’s somewhat inefficient, not complete enough (yet) for use as the brand new spell checking mode we are envisioning. There is no keyboard navigation in the overlay, and there are issues with the way we’d like mouse clicks in a non-transparent area to behave, along with other experimental and unfinished features.
There are issues with the overlay suggestions window when using the suggestions and completions pop-ups, when moving the document window around, and in other situations. Remember, this is just a temporary implementation of this functionality.
Related to efficiency, if “What to check:” is set to “Entire Document,” performance can be pretty bad for even moderately long documents.
NSTextView can report “interesting” values for the kEventParamTextInputReplyLineHeight and kEventParamTextInputReplyLineAscent parameters returned by kEventTextInputOffsetToPos for offsets on a line that is only partially visible at either the top or bottom of the view. Depending on various settings in the palette, the corresponding text in the overlay may not be drawn in the expected location. Same goes for paragraphs with specific Spacing values set (single and double seems OK, but that’s about all).
The accessibility support in the input method really only works well in NSTextView, and in a limited way with MLTE (mostly due to bugs in MLTE’s accessibility support). It would take a fair bit of work to support WebView, due to its (very different) AX implementation.
There have been almost enough text input-related bugs fixed in WebView, in the current Open Source TOT, for it to support this feature. There are some bugs remaining at the AppKit level related to the kEventTextInputOffsetToPos event with non-zero offsets when there is no active inline input area. Unfortunately, one of these problems causes an exception to be thrown, and things get pretty messed-up after that. Only Apple can fix this particular problem.
Text is rendered very close to where it appears onscreen under the overlay when using results obtained from TSM - but not quite exactly. Some of this is because TSM returns QuickDraw screen coordinates (integral) from kEventTextInputOffsetToPos, and some due to the somewhat finicky calculations that are required to figure out where a particular word should be drawn. Almost pixel-perfect results can be obtained using the bounds and RTF obtained using the AX APIs in an app using NSTextView (makes sense, since rendering in the overlay is very similar to how NSTextView itself would lay out the text).
It’s likely that the calculations made to figure out where to draw in the overlay based on what we get from the app aren’t quite right in all situations.
“Text” highlighting looks better with larger font sizes. “Background” highlighting doesn’t look all that great. Actually, I’m not at all happy with the way any highlighting is drawn. If someone with actual graphics/Quartz knowledge has any suggestions, I’m all ears.
Not all document changes are (or can be) observed in order to sync the overlay with the document. One example is using the font panel in TextEdit (and probably any other NSTextView). Another is using the ruler to make changes.
The “Visible Text” preference for “What to check:” requires accessibility for any kind of accurate results. It’s not really possible to determine the range of visible text via TSM.
The overlay covers the entire document window, including structural regions (title bar, grow area, scroll bar). Same goes even if the active text area occupies only a portion of the window. You can see this when changing the transparency of the overlay, and also see that text can be drawn over the scroll bars and title bar at times during scrolling.
“Use in all text areas” doesn’t seem to always work. Sometimes a new TSM document gets activated or created, but the overlay doesn’t automatically show. Often switching to another document and back helps.
Words that are long enough horizontally to be character-wrapped in the document aren’t drawn wrapped. It should be possible to get this working when using the bounds returned from AX, but not from TSM (there’s just no TSM API to truly determine this).
This stuff is all pretty new - if you think of something we could implement to help your testing or development, drop us a line. Same goes for problems and bug reports.
Notes: The Document Access command requires Mac OS X 10.4 (Tiger) or later.
Bonus: If you implement this support in your text engine, the Tiger Dictionary popup will “just work.”
| < Previous PageHelp IndexNext Page > |