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 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 int capacity = [speller->misspelled count] + 1;
119 NSMutableArray * misspelled = [NSMutableArray arrayWithCapacity:capacity];
120 [misspelled addObjectsFromArray:speller->misspelled];
121 [misspelled addObject:[NSValue valueWithRange:match]];
122 [speller->misspelled release];
123 speller->misspelled = [[NSArray arrayWithArray:misspelled] retain];
124 start = match.location + match.length + 1;
132 return [speller->misspelled count] ? SPELL_CHECK_FAILED : result;
136 void AppleSpeller_ignore(AppleSpeller speller, const char * word)
138 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
139 NSString * word_ = toString(word);
141 [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
148 size_t AppleSpeller_makeSuggestion(AppleSpeller speller, const char * word, const char * lang)
150 if (!speller->checker || !word || !lang)
153 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
154 NSString * word_ = toString(word);
155 NSString * lang_ = toString(lang);
158 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
159 // Mac OS X 10.6 only
160 NSInteger slen = [word_ length];
161 NSRange range = { 0, slen };
163 if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
164 result = [speller->checker guessesForWordRange:range
167 inSpellDocumentWithTag:speller->doctag];
169 [speller->checker setLanguage:lang_];
170 result = [speller->checker guessesForWord:word_];
173 [speller->checker setLanguage:lang_];
174 result = [speller->checker guessesForWord:word_];
180 [speller->suggestions release];
181 speller->suggestions = [[NSArray arrayWithArray:result] retain];
184 return [speller->suggestions count];
188 const char * AppleSpeller_getSuggestion(AppleSpeller speller, size_t pos)
190 const char * result = 0;
191 if (pos < [speller->suggestions count]) {
192 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
198 void AppleSpeller_learn(AppleSpeller speller, const char * word)
200 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
201 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
202 NSString * word_ = toString(word);
204 if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
205 [speller->checker learnWord:word_];
213 void AppleSpeller_unlearn(AppleSpeller speller, const char * word)
215 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
216 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
217 NSString * word_ = toString(word);
219 if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
220 [speller->checker unlearnWord:word_];
228 int AppleSpeller_numMisspelledWords(AppleSpeller speller)
230 return [speller->misspelled count];
234 void AppleSpeller_misspelledWord(AppleSpeller speller, int index, int * start, int * length)
236 NSRange range = [[speller->misspelled objectAtIndex:index] rangeValue];
237 *start = range.location;
238 *length = range.length;
242 int AppleSpeller_hasLanguage(AppleSpeller speller, const char * lang)
244 return toLanguage(speller, lang) != nil;