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 ([element isEqualToString:lang_]) {
75 } else if ([lang_ hasPrefix:element]) {
87 SpellCheckResult checkAppleSpeller(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;
98 [speller->misspelled release];
99 speller->misspelled = nil;
101 while (result == SPELL_CHECK_FAILED) {
102 NSRange match = [speller->checker
103 checkSpellingOfString:word_
107 inSpellDocumentWithTag:speller->doctag
110 result = match.length == 0 ? SPELL_CHECK_OK : SPELL_CHECK_FAILED;
111 if (result == SPELL_CHECK_OK) {
112 if ([NSSpellChecker instancesRespondToSelector:@selector(hasLearnedWord:)]) {
113 if ([speller->checker hasLearnedWord:word_])
114 result = SPELL_CHECK_LEARNED;
117 int capacity = [speller->misspelled count] + 1;
118 NSMutableArray * misspelled = [NSMutableArray arrayWithCapacity:capacity];
119 [misspelled addObjectsFromArray:speller->misspelled];
120 [misspelled addObject:[NSValue valueWithRange:match]];
121 [speller->misspelled release];
122 speller->misspelled = [[NSArray arrayWithArray:misspelled] retain];
123 start = match.location + match.length + 1;
131 return [speller->misspelled count] ? SPELL_CHECK_FAILED : result;
135 void ignoreAppleSpeller(AppleSpeller speller, const char * word)
137 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
138 NSString * word_ = toString(word);
140 [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
147 size_t makeSuggestionAppleSpeller(AppleSpeller speller, const char * word, const char * lang)
149 if (!speller->checker || !word || !lang)
152 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
153 NSString * word_ = toString(word);
154 NSString * lang_ = toString(lang);
157 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
158 // Mac OS X 10.6 only
159 NSInteger slen = [word_ length];
160 NSRange range = { 0, slen };
162 if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
163 result = [speller->checker guessesForWordRange:range
166 inSpellDocumentWithTag:speller->doctag];
168 [speller->checker setLanguage:lang_];
169 result = [speller->checker guessesForWord:word_];
172 [speller->checker setLanguage:lang_];
173 result = [speller->checker guessesForWord:word_];
179 [speller->suggestions release];
180 speller->suggestions = [[NSArray arrayWithArray:result] retain];
183 return [speller->suggestions count];
187 const char * getSuggestionAppleSpeller(AppleSpeller speller, size_t pos)
189 const char * result = 0;
190 if (pos < [speller->suggestions count]) {
191 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
197 void learnAppleSpeller(AppleSpeller speller, const char * word)
199 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
200 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
201 NSString * word_ = toString(word);
203 if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
204 [speller->checker learnWord:word_];
212 void unlearnAppleSpeller(AppleSpeller speller, const char * word)
214 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
215 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
216 NSString * word_ = toString(word);
218 if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
219 [speller->checker unlearnWord:word_];
227 int numMisspelledWordsAppleSpeller(AppleSpeller speller)
229 return [speller->misspelled count];
233 void misspelledWordAppleSpeller(AppleSpeller speller, int const position, int * start, int * length)
235 NSRange range = [[speller->misspelled objectAtIndex:position] rangeValue];
236 *start = range.location;
237 *length = range.length;
241 int hasLanguageAppleSpeller(AppleSpeller speller, const char * lang)
243 return toLanguage(speller, lang) != nil;