3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
11 #import <Carbon/Carbon.h>
12 #import <Cocoa/Cocoa.h>
14 #import <AvailabilityMacros.h>
16 #include "support/AppleSpeller.h"
18 typedef struct AppleSpellerRec {
19 NSSpellChecker * checker;
20 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
25 NSArray * suggestions;
30 AppleSpeller newAppleSpeller(void)
32 AppleSpeller speller = calloc(1, sizeof(AppleSpellerRec));
33 speller->checker = [NSSpellChecker sharedSpellChecker];
34 speller->doctag = [NSSpellChecker uniqueSpellDocumentTag];
35 speller->suggestions = nil;
36 speller->misspelled = nil;
41 void freeAppleSpeller(AppleSpeller speller)
43 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
45 [speller->checker closeSpellDocumentWithTag:speller->doctag];
47 [speller->suggestions release];
48 [speller->misspelled release];
56 static NSString * toString(const char * word)
58 return [[NSString alloc] initWithBytes:word length:strlen(word) encoding:NSUTF8StringEncoding];
62 static NSString * toLanguage(AppleSpeller speller, const char * lang)
64 NSString * result = nil;
65 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
66 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
67 NSString * lang_ = toString(lang);
68 if ([NSSpellChecker instancesRespondToSelector:@selector(availableLanguages)]) {
69 NSArray * languages = [speller->checker availableLanguages];
71 for (NSString *element in languages) {
72 if (0 == [element caseInsensitiveCompare:lang_]) {
75 } else if ([lang_ hasPrefix:element]) {
87 SpellCheckResult AppleSpeller_check(AppleSpeller speller, const char * word, const char * lang)
89 if (!speller->checker || !lang || !word)
90 return SPELL_CHECK_FAILED;
92 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
93 NSString * word_ = toString(word);
94 NSString * lang_ = toString(lang);
95 SpellCheckResult result = SPELL_CHECK_FAILED;
97 int length = [word_ length];
99 [speller->misspelled release];
100 speller->misspelled = nil;
102 while (result == SPELL_CHECK_FAILED && start < length) {
103 NSRange match = [speller->checker
104 checkSpellingOfString:word_
108 inSpellDocumentWithTag:speller->doctag
111 result = match.length == 0 ? SPELL_CHECK_OK : SPELL_CHECK_FAILED;
112 if (result == SPELL_CHECK_OK) {
113 if ([NSSpellChecker instancesRespondToSelector:@selector(hasLearnedWord:)]) {
114 if ([speller->checker hasLearnedWord:word_])
115 result = SPELL_CHECK_LEARNED;
118 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
119 NSUInteger capacity = [speller->misspelled count] + 1;
121 int capacity = [speller->misspelled count] + 1;
123 NSMutableArray * misspelled = [NSMutableArray arrayWithCapacity:capacity];
124 [misspelled addObjectsFromArray:speller->misspelled];
125 [misspelled addObject:[NSValue valueWithRange:match]];
126 [speller->misspelled release];
127 speller->misspelled = [[NSArray arrayWithArray:misspelled] retain];
128 start = match.location + match.length + 1;
136 return [speller->misspelled count] ? SPELL_CHECK_FAILED : result;
140 void AppleSpeller_ignore(AppleSpeller speller, const char * word)
142 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
143 NSString * word_ = toString(word);
145 [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
152 size_t AppleSpeller_makeSuggestion(AppleSpeller speller, const char * word, const char * lang)
154 if (!speller->checker || !word || !lang)
157 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
158 NSString * word_ = toString(word);
159 NSString * lang_ = toString(lang);
162 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
163 // Mac OS X 10.6 only
164 NSInteger slen = [word_ length];
165 NSRange range = { 0, slen };
167 if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
168 result = [speller->checker guessesForWordRange:range
171 inSpellDocumentWithTag:speller->doctag];
173 [speller->checker setLanguage:lang_];
174 result = [speller->checker guessesForWord:word_];
177 [speller->checker setLanguage:lang_];
178 result = [speller->checker guessesForWord:word_];
184 [speller->suggestions release];
185 speller->suggestions = [[NSArray arrayWithArray:result] retain];
188 return [speller->suggestions count];
192 const char * AppleSpeller_getSuggestion(AppleSpeller speller, size_t pos)
194 const char * result = 0;
195 if (pos < [speller->suggestions count]) {
196 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
202 void AppleSpeller_learn(AppleSpeller speller, const char * word)
204 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
205 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
206 NSString * word_ = toString(word);
208 if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
209 [speller->checker learnWord:word_];
217 void AppleSpeller_unlearn(AppleSpeller speller, const char * word)
219 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
220 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
221 NSString * word_ = toString(word);
223 if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
224 [speller->checker unlearnWord:word_];
232 int AppleSpeller_numMisspelledWords(AppleSpeller speller)
234 return [speller->misspelled count];
238 void AppleSpeller_misspelledWord(AppleSpeller speller, int index, int * start, int * length)
240 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
241 NSRange range = [[speller->misspelled objectAtIndex:(NSUInteger)index] rangeValue];
243 NSRange range = [[speller->misspelled objectAtIndex:index] rangeValue];
245 *start = range.location;
246 *length = range.length;
250 int AppleSpeller_hasLanguage(AppleSpeller speller, const char * lang)
252 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
253 return toLanguage(speller, lang) != nil;