]> git.lyx.org Git - lyx.git/blob - src/support/AppleSpeller.m
Add quote style information to languages
[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 <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         NSArray * suggestions;
26         NSArray * misspelled;
27 } AppleSpellerRec ;
28
29
30 AppleSpeller newAppleSpeller(void)
31 {
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;
37         return speller;
38 }
39
40
41 void freeAppleSpeller(AppleSpeller speller)
42 {
43         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
44
45         [speller->checker closeSpellDocumentWithTag:speller->doctag];
46
47         [speller->suggestions release];
48         [speller->misspelled release];
49
50         [pool release];
51
52         free(speller);
53 }
54
55
56 static NSString * toString(const char * word)
57 {
58         return [[NSString alloc] initWithBytes:word length:strlen(word) encoding:NSUTF8StringEncoding];
59 }
60
61
62 static NSString * toLanguage(AppleSpeller speller, const char * lang)
63 {
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];
70                 
71                 for (NSString *element in languages) {
72                         if (0 == [element caseInsensitiveCompare:lang_]) {
73                                 result = element;
74                                 break;
75                         } else if ([lang_ hasPrefix:element]) {
76                                 result = element;
77                         }
78                 }
79         }
80         [lang_ release];
81         [pool release];
82 #endif
83         return result;
84 }
85
86
87 SpellCheckResult AppleSpeller_check(AppleSpeller speller, const char * word, const char * lang)
88 {
89         if (!speller->checker || !lang || !word)
90                 return SPELL_CHECK_FAILED;
91
92         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
93         NSString * word_ = toString(word);
94         NSString * lang_ = toString(lang);
95         SpellCheckResult result = SPELL_CHECK_FAILED;
96         int start = 0;
97         int length = [word_ length];
98         
99         [speller->misspelled release];
100         speller->misspelled = nil;
101
102         while (result == SPELL_CHECK_FAILED && start < length) {
103                 NSRange match = [speller->checker
104                         checkSpellingOfString:word_
105                         startingAt:start
106                         language:lang_
107                         wrap:(BOOL)NO
108                         inSpellDocumentWithTag:speller->doctag
109                         wordCount:NULL];
110
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;
116                         }
117                 } else {
118 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
119                         NSUInteger capacity = [speller->misspelled count] + 1;
120 #else
121                         int capacity = [speller->misspelled count] + 1;
122 #endif
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;
129                 }
130         }
131
132         [word_ release];
133         [lang_ release];
134         [pool release];
135
136         return [speller->misspelled count] ? SPELL_CHECK_FAILED : result;
137 }
138
139
140 void AppleSpeller_ignore(AppleSpeller speller, const char * word)
141 {
142         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
143         NSString * word_ = toString(word);
144
145         [speller->checker ignoreWord:word_ inSpellDocumentWithTag:(speller->doctag)];
146
147         [word_ release];
148         [pool release];
149 }
150
151
152 size_t AppleSpeller_makeSuggestion(AppleSpeller speller, const char * word, const char * lang)
153 {
154         if (!speller->checker || !word || !lang)
155                 return 0;
156
157         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
158         NSString * word_ = toString(word);
159         NSString * lang_ = toString(lang);
160         NSArray * result ;
161
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 };
166         
167         if ([NSSpellChecker instancesRespondToSelector:@selector(guessesForWordRange:)]) {
168                 result = [speller->checker guessesForWordRange:range
169                         inString:word_
170                         language:lang_
171                         inSpellDocumentWithTag:speller->doctag];
172         } else {
173                 [speller->checker setLanguage:lang_];
174                 result = [speller->checker guessesForWord:word_];
175         }
176 #else
177         [speller->checker setLanguage:lang_];
178         result = [speller->checker guessesForWord:word_];
179 #endif
180
181         [word_ release];
182         [lang_ release];
183
184         [speller->suggestions release];
185         speller->suggestions = [[NSArray arrayWithArray:result] retain];
186
187         [pool release];
188         return [speller->suggestions count];
189 }
190
191
192 const char * AppleSpeller_getSuggestion(AppleSpeller speller, size_t pos)
193 {
194         const char * result = 0;
195         if (pos < [speller->suggestions count]) {
196                 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
197         }
198         return result;
199 }
200
201
202 void AppleSpeller_learn(AppleSpeller speller, const char * word)
203 {
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);
207
208         if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
209                 [speller->checker learnWord:word_];
210         
211         [word_ release];
212         [pool release];
213 #endif
214 }
215
216
217 void AppleSpeller_unlearn(AppleSpeller speller, const char * word)
218 {
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);
222
223         if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
224                 [speller->checker unlearnWord:word_];
225         
226         [word_ release];
227         [pool release];
228 #endif
229 }
230
231
232 int AppleSpeller_numMisspelledWords(AppleSpeller speller)
233 {
234         return [speller->misspelled count];
235 }
236
237
238 void AppleSpeller_misspelledWord(AppleSpeller speller, int index, int * start, int * length)
239 {
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];
242 #else
243         NSRange range = [[speller->misspelled objectAtIndex:index] rangeValue];
244 #endif
245         *start = range.location;
246         *length = range.length;
247 }
248
249
250 int AppleSpeller_hasLanguage(AppleSpeller speller, const char * lang)
251 {
252 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
253         return toLanguage(speller, lang) != nil;
254 #else
255         return true;
256 #endif
257 }