]> err.no Git - sope/blob - sope-core/NGExtensions/FdExt.subproj/NSString+German.m
fixed -isAfternoon method
[sope] / sope-core / NGExtensions / FdExt.subproj / NSString+German.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "NSString+German.h"
24 #include "common.h"
25
26 @implementation NSString(German)
27
28 - (BOOL)doesContainGermanUmlauts {
29   register unsigned i, len;
30   
31   if ((len = [self length]) == 0)
32     return NO;
33   
34   for (i = 0; i < len; i++) {
35     switch ([self characterAtIndex:i]) {
36       case 252: /* &uuml; */
37       case 220: /* &Uuml; */
38       case 228: /* &auml; */
39       case 196: /* &Auml; */
40       case 246: /* &ouml; */
41       case 214: /* &Ouml; */
42       case 223: /* &szlig; */
43         return YES;
44     }
45   }
46   return NO;
47 }
48
49 - (NSString *)stringByReplacingGermanUmlautsWithTwoCharsAndSzWith:(unichar)_c {
50   /*
51     a^ => ae, o^ => oe, u^ => ue, A^ => Ae, O^ => Oe, O^ => Ue
52     s^ => sz or ss (_sz arg)
53   */
54   unsigned i, len, rlen;
55   unichar  *buf;
56   NSString *s;
57   
58   if ((len = [self length]) == 0)
59     return @"";
60   
61   buf = calloc((len * 2) + 3, sizeof(unichar));
62   
63   for (i = 0, rlen = 0; i < len; i++) {
64     // TODO
65     register unichar c;
66     
67     c = [self characterAtIndex:i];
68     switch (c) {
69       case 252: /* ue */
70         buf[rlen] = 'u'; rlen++;
71         buf[rlen] = 'e'; rlen++;
72         break;
73       case 220: /* Ue */
74         buf[rlen] = 'U'; rlen++;
75         buf[rlen] = 'e'; rlen++;
76         break;
77       case 228: /* ae */
78         buf[rlen] = 'a'; rlen++;
79         buf[rlen] = 'e'; rlen++;
80         break;
81       case 196: /* Ae */
82         buf[rlen] = 'A'; rlen++;
83         buf[rlen] = 'e'; rlen++;
84         break;
85       case 246: /* oe */
86         buf[rlen] = 'o'; rlen++;
87         buf[rlen] = 'e'; rlen++;
88         break;
89       case 214: /* Oe */
90         buf[rlen] = 'O'; rlen++;
91         buf[rlen] = 'e'; rlen++;
92         break;
93       case 223: /* ss or sz */
94         // TODO
95         buf[rlen] = 's'; rlen++;
96         buf[rlen] = _c;  rlen++;
97         break;
98         
99     default: /* copy char and continue */
100       buf[rlen] = c;
101       rlen++;
102       break;
103     }
104   }
105   
106   s = (rlen > len)
107     ? [[NSString alloc] initWithCharacters:buf length:rlen]
108     : [self copy];
109   if (buf) free(buf);
110   return [s autorelease];
111 }
112 - (NSString *)stringByReplacingGermanUmlautsWithTwoChars {
113   // default sz mapping is "ss" (like Hess ;-)
114   return [self stringByReplacingGermanUmlautsWithTwoCharsAndSzWith:'s'];
115 }
116
117 - (NSString *)stringByReplacingTwoCharEncodingsOfGermanUmlauts {
118   /*
119     ae => a^, oe => o^, ue => u^, Ae => A^, Oe => O^, Ue => U^
120     sz => s^
121     ss => s^
122   */
123   unsigned i, len, rlen;
124   NSString *s;
125   unichar  *buf;
126   BOOL     didReplace;
127   
128   if ((len = [self length]) == 0)
129     return @"";
130   if (len == 1)
131     return [[self copy] autorelease];
132   
133   buf = calloc(len + 3, sizeof(unichar));
134   [self getCharacters:buf]; // Note: we can reuse that buffer!
135   
136   for (i = 0, rlen = 0, didReplace = NO; i < len; i++) {
137     register unichar c, cn;
138     
139     c = buf[i];
140
141     if ((i + 1) >= len) {
142       buf[rlen] = c;
143       rlen++;
144       break; // end, found last char (so can't be a sequence)
145     }
146
147     cn = buf[i + 1];
148     
149     if ((c=='a' || c=='A' || c=='u' || c=='U' || c=='o' || c=='O')&&cn=='e') {
150       /* an umlaut sequence */
151       switch (c) {
152       case 'a': buf[rlen] = 228; break;
153       case 'A': buf[rlen] = 196; break;
154       case 'o': buf[rlen] = 246; break;
155       case 'O': buf[rlen] = 214; break;
156       case 'u': buf[rlen] = 252; break;
157       case 'U': buf[rlen] = 220; break;
158       }
159       rlen++;
160       i++; // skip sequence char
161       didReplace = YES;
162     }
163     else if (c == 's' && (cn == 's' || cn == 'z')) {
164       /* a sz sequence */
165       buf[rlen] = 223;
166       rlen++;
167       i++; // skip sequence char
168       didReplace = YES;
169     }
170     else {
171       /* regular char, copy */
172       buf[rlen] = c;
173       rlen++;
174     }
175   }
176   
177   s = didReplace
178     ? [[NSString alloc] initWithCharacters:buf length:rlen]
179     : [self copy];
180   if (buf) free(buf);
181   return [s autorelease];
182 }
183
184 - (NSArray *)germanUmlautVariantsOfString {
185   /*
186     The ^ is used to signal the single character umlaut to avoid non-ASCII
187     source code.
188     
189     Note: we can only do a limited set of transformations! Eg you can only
190           mix umlauts *OR* the "ue", "oe" variants!
191     
192     Q: what about names which contain encoded umlauts *and* the same sequence
193        as a regular part of the name! For example "Neuendoerf".
194     
195     string with umlauts (two variants, ss and sz):
196       a^ => ae
197       o^ => oe
198       u^ => ue
199       A^ => Ae
200       O^ => Oe
201       O^ => Ue
202       s^ => sz & ss
203     
204     string with umlaut workaround (three variants due to sz/ss):
205       ae => a^
206       oe => o^
207       ue => u^
208       Ae => A^
209       Oe => O^
210       Ue => U^
211       sz => s^ & sz // ?
212       ss => s^ & ss // ?
213   */
214   NSString *s1, *s2;
215   unsigned len;
216   
217   if ((len = [self length]) == 0)
218     return [NSArray arrayWithObjects:@"", nil];
219   
220   if ([self doesContainGermanUmlauts]) {
221     s1 = [self stringByReplacingGermanUmlautsWithTwoCharsAndSzWith:'s'];
222     s2 = [self stringByReplacingGermanUmlautsWithTwoCharsAndSzWith:'z'];
223     
224     if ([s2 isEqualToString:s1] || [s2 isEqualToString:self])
225       s2 = nil;
226     if ([s1 isEqualToString:self])
227       s1 = s2;
228     
229     return [NSArray arrayWithObjects:self, s1, s2, nil];
230   }
231   
232   if (len < 2) // a sequence would have at least 2 chars
233     return [NSArray arrayWithObjects:self, nil];
234   
235   s1 = [self stringByReplacingTwoCharEncodingsOfGermanUmlauts];
236   
237   if ([self isEqualToString:s1])
238     /* nothing was replaced */
239     return [NSArray arrayWithObjects:self, nil];
240   
241   return [NSArray arrayWithObjects:self, s1, nil];
242 }
243
244 @end /* NSString(German) */