]> git.lyx.org Git - lyx.git/blob - src/support/AppleSpeller.m
Only create a new view for lyxfiles-open if no view is open (#12894)
[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         result = [speller->checker guessesForWordRange:range
167                 inString:word_
168                 language:lang_
169                 inSpellDocumentWithTag:speller->doctag];
170 #else
171         [speller->checker setLanguage:lang_];
172         result = [speller->checker guessesForWord:word_];
173 #endif
174
175         [word_ release];
176         [lang_ release];
177
178         [speller->suggestions release];
179         speller->suggestions = [[NSArray arrayWithArray:result] retain];
180
181         [pool release];
182         return [speller->suggestions count];
183 }
184
185
186 const char * AppleSpeller_getSuggestion(AppleSpeller speller, size_t pos)
187 {
188         const char * result = 0;
189         if (pos < [speller->suggestions count]) {
190                 result = [[speller->suggestions objectAtIndex:pos] UTF8String] ;
191         }
192         return result;
193 }
194
195
196 void AppleSpeller_learn(AppleSpeller speller, const char * word)
197 {
198 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
199         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
200         NSString * word_ = toString(word);
201
202         if ([NSSpellChecker instancesRespondToSelector:@selector(learnWord:)])
203                 [speller->checker learnWord:word_];
204
205         [word_ release];
206         [pool release];
207 #endif
208 }
209
210
211 void AppleSpeller_unlearn(AppleSpeller speller, const char * word)
212 {
213 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
214         NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
215         NSString * word_ = toString(word);
216
217         if ([NSSpellChecker instancesRespondToSelector:@selector(unlearnWord:)])
218                 [speller->checker unlearnWord:word_];
219
220         [word_ release];
221         [pool release];
222 #endif
223 }
224
225
226 int AppleSpeller_numMisspelledWords(AppleSpeller speller)
227 {
228         return [speller->misspelled count];
229 }
230
231
232 void AppleSpeller_misspelledWord(AppleSpeller speller, int index, int * start, int * length)
233 {
234 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
235         NSRange range = [[speller->misspelled objectAtIndex:(NSUInteger)index] rangeValue];
236 #else
237         NSRange range = [[speller->misspelled objectAtIndex:index] rangeValue];
238 #endif
239         *start = range.location;
240         *length = range.length;
241 }
242
243
244 int AppleSpeller_hasLanguage(AppleSpeller speller, const char * lang)
245 {
246 #if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050)
247         return toLanguage(speller, lang) != nil;
248 #else
249         return true;
250 #endif
251 }