]> git.lyx.org Git - lyx.git/blob - src/support/AppleSpeller.m
Fix problem with python and change of PATH
[lyx.git] / src / support / AppleSpeller.m
1 /**
2  * \file AppleSpeller.m
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Stephan Witt
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #import <Cocoa/Cocoa.h>
12
13 #import <AvailabilityMacros.h>
14
15 #include "support/AppleSpeller.h"
16
17 typedef struct AppleSpellerRec {
18         NSSpellChecker * checker;
19 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
20         NSInteger doctag;
21 #else
22         int doctag;
23 #endif
24         NSArray * suggestions;
25         NSArray * misspelled;
26 } AppleSpellerRec ;
27
28
29 AppleSpeller newAppleSpeller(void)
30 {
31         AppleSpeller speller = calloc(1, sizeof(AppleSpellerRec));
32         speller->checker = [NSSpellChecker sharedSpellChecker];
33         speller->doctag = [NSSpellChecker uniqueSpellDocumentTag];
34         speller->suggestions = nil;
35         speller->misspelled = nil;
36         return speller;
37 }
38
39
40 void freeAppleSpeller(AppleSpeller speller)
41 {
42         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
43
44         [speller->checker closeSpellDocumentWithTag:speller->doctag];
45
46         [speller->suggestions release];
47         [speller->misspelled release];
48
49         [pool release];
50
51         free(speller);
52 }
53
54
55 static NSString * toString(const char * word)
56 {
57         return [[NSString alloc] initWithBytes:word length:strlen(word) encoding:NSUTF8StringEncoding];
58 }
59
60
61 static NSString * toLanguage(AppleSpeller speller, const char * lang)
62 {
63         NSString * result = nil;
64 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
65         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
66         NSString * lang_ = toString(lang);
67         if ([NSSpellChecker instancesRespondToSelector:@selector(availableLanguages)]) {
68                 NSArray * languages = [speller->checker availableLanguages];
69                 
70                 for (NSString *element in languages) {
71                         if (0 == [element caseInsensitiveCompare:lang_]) {
72                                 result = element;
73                                 break;
74                         } else if ([lang_ hasPrefix:element]) {
75                                 result = element;
76                         }
77                 }
78         }
79         [lang_ release];
80         [pool release];
81 #endif
82         return result;
83 }
84
85
86 SpellCheckResult AppleSpeller_check(AppleSpeller speller, const char * word, const char * lang)
87 {
88         if (!speller->checker || !lang || !word)
89                 return SPELL_CHECK_FAILED;
90
91         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
92         NSString * word_ = toString(word);
93         NSString * lang_ = toString(lang);
94         SpellCheckResult result = SPELL_CHECK_FAILED;
95         int start = 0;
96         int length = [word_ length];
97         
98         [speller->misspelled release];
99         speller->misspelled = nil;
100
101         while (result == SPELL_CHECK_FAILED && start < length) {
102                 NSRange match = [speller->checker
103                         checkSpellingOfString:word_
104                         startingAt:start
105                         language:lang_
106                         wrap:(BOOL)NO
107                         inSpellDocumentWithTag:speller->doctag
108                         wordCount:NULL];
109
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;
115                         }
116                 } else {
117 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
118                         NSUInteger capacity = [speller->misspelled count] + 1;
119 #else
120                         int capacity = [speller->misspelled count] + 1;
121 #endif
122                         NSMutableArray * misspelled = [NSMutableArray arrayWithCapacity:capacity];
123                         [misspelled addObjectsFromArray:speller->misspelled];
124                         [misspelled addObject:[NSValue valueWithRange:match]];
125                         [speller->misspelled release];
126                         speller->misspelled = [[NSArray arrayWithArray:misspelled] retain];
127                         start = match.location + match.length + 1;
128                 }
129         }
130
131         [word_ release];
132         [lang_ release];
133         [pool release];
134
135         return [speller->misspelled count] ? SPELL_CHECK_FAILED : result;
136 }
137
138
139 void AppleSpeller_ignore(AppleSpeller speller, const char * word)
140 {
141         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
142         NSString * word_ = toString(word);
143
144         [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
145
146         [word_ release];
147         [pool release];
148 }
149
150
151 size_t AppleSpeller_makeSuggestion(AppleSpeller speller, const char * word, const char * lang)
152 {
153         if (!speller->checker || !word || !lang)
154                 return 0;
155
156         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
157         NSString * word_ = toString(word);
158         NSString * lang_ = toString(lang);
159         NSArray * result ;
160
161 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
162         // Mac OS X 10.6 only
163         NSInteger slen = [word_ length];
164         NSRange range = { 0, slen };
165         
166         if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
167                 result = [speller->checker guessesForWordRange:range
168                         inString:word_
169                         language:lang_
170                         inSpellDocumentWithTag:speller->doctag];
171         } else {
172                 [speller->checker setLanguage:lang_];
173                 result = [speller->checker guessesForWord:word_];
174         }
175 #else
176         [speller->checker setLanguage:lang_];
177         result = [speller->checker guessesForWord:word_];
178 #endif
179
180         [word_ release];
181         [lang_ release];
182
183         [speller->suggestions release];
184         speller->suggestions = [[NSArray arrayWithArray:result] retain];
185
186         [pool release];
187         return [speller->suggestions count];
188 }
189
190
191 const char * AppleSpeller_getSuggestion(AppleSpeller speller, size_t pos)
192 {
193         const char * result = 0;
194         if (pos < [speller->suggestions count]) {
195                 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
196         }
197         return result;
198 }
199
200
201 void AppleSpeller_learn(AppleSpeller speller, const char * word)
202 {
203 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
204         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
205         NSString * word_ = toString(word);
206
207         if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
208                 [speller->checker learnWord:word_];
209         
210         [word_ release];
211         [pool release];
212 #endif
213 }
214
215
216 void AppleSpeller_unlearn(AppleSpeller speller, const char * word)
217 {
218 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
219         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
220         NSString * word_ = toString(word);
221
222         if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
223                 [speller->checker unlearnWord:word_];
224         
225         [word_ release];
226         [pool release];
227 #endif
228 }
229
230
231 int AppleSpeller_numMisspelledWords(AppleSpeller speller)
232 {
233         return [speller->misspelled count];
234 }
235
236
237 void AppleSpeller_misspelledWord(AppleSpeller speller, int index, int * start, int * length)
238 {
239 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
240         NSRange range = [[speller->misspelled objectAtIndex:(NSUInteger)index] rangeValue];
241 #else
242         NSRange range = [[speller->misspelled objectAtIndex:index] rangeValue];
243 #endif
244         *start = range.location;
245         *length = range.length;
246 }
247
248
249 int AppleSpeller_hasLanguage(AppleSpeller speller, const char * lang)
250 {
251 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
252         return toLanguage(speller, lang) != nil;
253 #else
254         return true;
255 #endif
256 }