]> git.lyx.org Git - features.git/blob - src/support/AppleSpeller.m
Implement LFUN_SPELLING_REMOVE (patch from switt)
[features.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 <Carbon/Carbon.h>
12 #import <Cocoa/Cocoa.h>
13
14 #import <AvailabilityMacros.h>
15
16 #include "support/AppleSpeller.h"
17
18 typedef struct AppleSpellerRec {
19         NSSpellChecker * checker;
20 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
21         NSInteger doctag;
22 #else
23         int doctag;
24 #endif
25         char ** suggestions;
26         size_t numsug;
27 } AppleSpellerRec ;
28
29
30 static void freeSuggestionsAppleSpeller(AppleSpeller speller)
31 {
32         if (speller->suggestions) {
33                 while (speller->numsug--) {
34                         free(speller->suggestions[speller->numsug]);
35                 }
36                 free(speller->suggestions);
37                 speller->suggestions = 0;
38         }
39 }
40
41
42 AppleSpeller newAppleSpeller(void)
43 {
44         AppleSpeller speller = calloc(1, sizeof(AppleSpellerRec));
45         speller->checker = [NSSpellChecker sharedSpellChecker];
46         speller->suggestions = 0;
47         speller->doctag = [NSSpellChecker uniqueSpellDocumentTag];
48         return speller;
49 }
50
51
52 void freeAppleSpeller(AppleSpeller speller)
53 {
54         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
55
56         freeSuggestionsAppleSpeller(speller);
57         [speller->checker closeSpellDocumentWithTag:speller->doctag];
58
59         [pool release];
60
61         free(speller);
62 }
63
64
65 static NSString * toString(const char * word)
66 {
67         return [[NSString alloc] initWithBytes:word length:strlen(word) encoding:NSUTF8StringEncoding];
68 }
69
70
71 SpellCheckResult checkAppleSpeller(AppleSpeller speller, const char * word, const char * lang)
72 {
73         if (!speller->checker || !lang || !word)
74                 return SPELL_CHECK_FAILED;
75
76         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
77         NSString * word_ = toString(word);
78         NSString * lang_ = toString(lang);
79
80         NSRange match = [speller->checker
81                 checkSpellingOfString:word_
82                 startingAt:0
83                 language:lang_
84                 wrap:NO
85                 inSpellDocumentWithTag:speller->doctag
86                 wordCount:NULL];
87
88         SpellCheckResult result = match.length == 0 ? SPELL_CHECK_OK : SPELL_CHECK_FAILED;
89         if (result == SPELL_CHECK_OK && [NSSpellChecker instancesRespondToSelector:@selector(hasLearnedWord:)]) {
90                 if ([speller->checker hasLearnedWord:word_])
91                         result = SPELL_CHECK_LEARNED;
92         }
93
94         [word_ release];
95         [lang_ release];
96         [pool release];
97
98         return result;
99 }
100
101
102 void ignoreAppleSpeller(AppleSpeller speller, const char * word)
103 {
104         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
105         NSString * word_ = toString(word);
106
107         [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
108
109         [word_ release];
110         [pool release];
111 }
112
113
114 size_t makeSuggestionAppleSpeller(AppleSpeller speller, const char * word, const char * lang)
115 {
116         if (!speller->checker || !word || !lang)
117                 return 0;
118
119         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
120         NSString * word_ = toString(word);
121         NSString * lang_ = toString(lang);
122         NSArray * result ;
123
124 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
125         // Mac OS X 10.6 only
126         NSInteger slen = [word_ length];
127         NSRange range = { 0, slen };
128         
129         if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
130                 result = [speller->checker guessesForWordRange:range
131                         inString:word_
132                         language:lang_
133                         inSpellDocumentWithTag:speller->doctag];
134         } else {
135                 [speller->checker setLanguage:lang_];
136                 result = [speller->checker guessesForWord:word_];
137         }
138 #else
139         [speller->checker setLanguage:lang_];
140         result = [speller->checker guessesForWord:word_];
141 #endif
142
143         [word_ release];
144         [lang_ release];
145
146         freeSuggestionsAppleSpeller(speller);
147
148         speller->numsug = [result count];
149         if (speller->numsug) {
150                 speller->suggestions = calloc(speller->numsug + 1, sizeof(char *));
151                 if (speller->suggestions) {
152                         size_t i;
153                         for (i = 0; i < speller->numsug; i++) {
154                                 NSString * str = [result objectAtIndex:i];
155                                 speller->suggestions[i] = strdup([str UTF8String]);
156                         }
157                         speller->suggestions[speller->numsug] = 0;
158                 }
159         }
160         [pool release];
161         return speller->numsug;
162 }
163
164
165 const char * getSuggestionAppleSpeller(AppleSpeller speller, size_t pos)
166 {
167         const char * result = 0;
168         if (pos < speller->numsug && speller->suggestions) {
169                 result = speller->suggestions[pos] ;
170         }
171         return result;
172 }
173
174
175 void learnAppleSpeller(AppleSpeller speller, const char * word)
176 {
177 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
178         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
179         NSString * word_ = toString(word);
180
181         if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
182                 [speller->checker learnWord:word_];
183         
184         [word_ release];
185         [pool release];
186 #endif
187 }
188
189
190
191 void unlearnAppleSpeller(AppleSpeller speller, const char * word)
192 {
193 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
194         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
195         NSString * word_ = toString(word);
196
197         if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
198                 [speller->checker unlearnWord:word_];
199         
200         [word_ release];
201         [pool release];
202 #endif
203 }
204
205
206 int hasLanguageAppleSpeller(AppleSpeller speller, const char * lang)
207 {
208         BOOL result = NO;
209 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
210         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
211         NSString * lang_ = toString(lang);
212         if ([NSSpellChecker instancesRespondToSelector:@selector(availableLanguages:)]) {
213                 NSArray * languages = [speller->checker availableLanguages];
214
215                 for (NSString *element in languages) {
216                         result = [element isEqualToString:lang_] || [lang_ hasPrefix:element];
217                         if (result) break;
218                 }
219         }
220
221         [lang_ release];
222         [pool release];
223 #endif
224
225         return result ? 1 : 0;
226 }