source: trunk/Cocoa/Pester/Source/NJRDateFormatter.m@ 361

Last change on this file since 361 was 361, checked in by Nicholas Riley, 16 years ago

VERSION: Updated for 1.1b5.

English.lproj/InfoPlist.strings: Updated for 1.1b5.

English.lproj/MainMenu.nib: Change IB compatibility level to 10.4.
Disable controls which lead to unstable functionality in this version.
Added Sparkle support. Hook up removeMessageButton to
PSAlarmSetController for "-" fallback drawing.

English.lproj/Preferences.nib: Added Sparkle checkbox.

English.lproj/Read Me.nib: Leopard-ized with source list coloring,
highlight and removed focus ring (which caused artifacts anyway).

English.lproj/Snooze until.nib: Use new natural language date strings
and calendar button bezel style.

Info-Pester.plist: Updated for 1.1b5. Added Sparkle support.

NJRDateFormatter.m: Comment out debug logging on every keystroke.

PSAlarmSetController.[hm]: If "-" image exists (on Leopard), don't
draw it with text as well.

PSAlerts.m: Don't describe bounce alert (which is present for
backwards compatibility, but doesn't work yet in this version).

PSPowerManager.m: Temporarily disable; untested in this version.

Pester.xcodeproj: Change Development/Deployment to Debug/Release.
Link to Sparkle. STRIP_INSTALLED_PRODUCT=NO on release version for
now (eventually, can investigate using symbol files).

Read Me.rtfd: Updated for 1.1b5. Use real links. Clean up release
notes. Credit Sparkle and Date::Manip. Clean up styles so they look
better in the read me viewer. Fix Omni link.

Sparkle.diff: Changes to Sparkle, which is included as an external.
These aren't yet automatically applied.

Updates/Application icon.png: The icon converted to a PNG. This will
probably go away as it's too big.

Updates/release-notes.css: Release notes CSS based on the example that
comes with Sparkle.

Updates/release-notes.html: Dummy release notes file; nobody should
see this yet.

Updates/updates.xml: Initial Sparkle appcast file.

package-Pester.sh: Update for xcodebuild, Sparkle, etc. No longer
include source in download.

File size: 6.0 KB
RevLine 
[21]1//
2// NJRDateFormatter.m
3// Pester
4//
5// Created by Nicholas Riley on Wed Oct 09 2002.
6// Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9#import "NJRDateFormatter.h"
10
[360]11// generated by perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c
12#include <EXTERN.h>
13#include <perl.h>
[21]14
[360]15EXTERN_C void xs_init (pTHX);
[21]16
[360]17EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
[43]18
[360]19EXTERN_C void
20xs_init(pTHX)
[43]21{
[360]22 char *file = __FILE__;
23 dXSUB_SYS;
24
25 /* DynaLoader is a special case */
26 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
[43]27}
[360]28// end generated code
[43]29
[360]30static PerlInterpreter *my_perl;
31static NSDateFormatter *dateManipFormatter;
[43]32
[360]33static NSDate *parse_natural_language_date(NSString *input) {
34 if (my_perl == NULL) return nil;
35
36 if ([input rangeOfString: @"|"].length > 0) {
37 NSMutableString *sanitized = [[input mutableCopy] autorelease];
38 [sanitized replaceOccurrencesOfString: @"|" withString: @""
39 options: NSLiteralSearch
40 range: NSMakeRange(0, [sanitized length])];
41 input = sanitized;
42 }
43
44 NSString *temp = [[NSString alloc] initWithFormat: @"UnixDate(q|%@|, '%%q')", input];
[361]45 // NSLog(@"%@", temp);
[360]46 SV *d = eval_pv([temp UTF8String], TRUE);
47 [temp release];
48 if (d == NULL) return nil;
49
50 STRLEN s_len;
51 char *s = SvPV(d, s_len);
52 if (s == NULL || s_len == 0) return nil;
53
54 NSDate *date = [dateManipFormatter dateFromString: [NSString stringWithUTF8String: s]];
[361]55 // NSLog(@"%@", date);
[360]56
57 return date;
[43]58}
59
[360]60static void init_perl(void) {
61 const char *argv[] = {"", "-CSD", "-I", "", "-MDate::Manip", "-e", "0"};
62 argv[3] = [[[NSBundle mainBundle] resourcePath] fileSystemRepresentation];
63 PERL_SYS_INIT(0, NULL);
64 my_perl = perl_alloc();
65 if (my_perl == NULL) return;
66
67 perl_construct(my_perl);
68 if (perl_parse(my_perl, xs_init, 7, (char **)argv, NULL) != 0) goto fail;
69
70 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
71 if (perl_run(my_perl) != 0) goto fail;
72
73 // XXX detect localization changes
74 eval_pv("Date_Init(\"Language=English\", \"DateFormat=non-US\", \"Internal=1\"", TRUE);
[43]75
[360]76 if (parse_natural_language_date(@"tomorrow") == nil) goto fail;
77
78 return;
79
80fail:
81 perl_destruct(my_perl);
82 perl_free(my_perl);
83 PERL_SYS_TERM();
84 my_perl = NULL;
[43]85}
86
[21]87// workaround for bug in Jaguar (and earlier?) NSCalendarDate dateWithNaturalLanguageString:
[360]88NSString *stringByRemovingSurroundingWhitespace(NSString *string) {
[21]89 static NSCharacterSet *nonWhitespace = nil;
90 NSRange firstValidCharacter, lastValidCharacter;
[360]91
[21]92 if (!nonWhitespace) {
93 nonWhitespace = [[[NSCharacterSet characterSetWithCharactersInString:
[360]94 @" \t\r\n"] invertedSet] retain];
[21]95 }
[360]96
[21]97 firstValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace];
98 if (firstValidCharacter.length == 0)
99 return @"";
[43]100 lastValidCharacter = [string rangeOfCharacterFromSet:nonWhitespace options: NSBackwardsSearch];
[360]101
[21]102 if (firstValidCharacter.location == 0 && lastValidCharacter.location == [string length] - 1)
103 return string;
104 else
[43]105 return [string substringWithRange: NSUnionRange(firstValidCharacter, lastValidCharacter)];
[21]106}
107
[360]108static const NSDateFormatterStyle formatterStyles[] = {
109 NSDateFormatterShortStyle,
110 NSDateFormatterMediumStyle,
111 NSDateFormatterLongStyle,
112 NSDateFormatterFullStyle,
113 NSDateFormatterNoStyle
114};
115
116@implementation NJRDateFormatter
117
118#pragma mark initialize-release
119
120+ (void)initialize;
[43]121{
[360]122 dateManipFormatter = [[NSDateFormatter alloc] init];
123 [dateManipFormatter setDateFormat: @"yyyyMMddHHmmss"]; // Date::Manip's "%q"
124 init_perl();
125}
126
127+ (NJRDateFormatter *)dateFormatter;
128{
129 NJRDateFormatter *formatter = [[self alloc] init];
130 NSMutableArray *tryFormatters = [[NSMutableArray alloc] init];
131
132 for (NSDateFormatterStyle *s = formatterStyles ; *s < NSDateFormatterNoStyle ; *s++) {
133 NSDateFormatter *tryFormatter = [[NSDateFormatter alloc] init];
134 [tryFormatter setLenient: YES];
135 [tryFormatter setTimeStyle: NSDateFormatterNoStyle];
136 [tryFormatter setDateStyle: *s];
137 [tryFormatters addObject: tryFormatter];
138 [tryFormatter release];
[43]139 }
[360]140 // XXX do this in init
141 formatter->tryFormatters = tryFormatters;
142
143 return [formatter autorelease];
[43]144}
[21]145
[360]146+ (NJRDateFormatter *)timeFormatter;
147{
148 NJRDateFormatter *formatter = [[self alloc] init];
149 NSMutableArray *tryFormatters = [[NSMutableArray alloc] init];
150
151 for (NSDateFormatterStyle *s = formatterStyles ; *s < NSDateFormatterNoStyle ; *s++) {
152 NSDateFormatter *tryFormatter = [[NSDateFormatter alloc] init];
153 [tryFormatter setLenient: YES];
154 [tryFormatter setTimeStyle: *s];
155 [tryFormatter setDateStyle: NSDateFormatterNoStyle];
156 [tryFormatters addObject: tryFormatter];
157 [tryFormatter release];
158 }
159 formatter->tryFormatters = tryFormatters;
160
161 return [formatter autorelease];
162}
163
[43]164- (void)dealloc;
165{
[360]166 [tryFormatters release]; tryFormatters = nil;
[43]167 [super dealloc];
168}
169
[360]170#pragma mark primitive formatter
171
172- (NSString *)stringForObjectValue:(id)obj;
173{
174 return [super stringForObjectValue: obj];
175}
176
177- (NSAttributedString *)attributedStringForObjectValue:(id)obj withDefaultAttributes:(NSDictionary *)attrs;
178{
179 return [super attributedStringForObjectValue: obj
180 withDefaultAttributes: attrs];
181}
182
[21]183- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
184{
[360]185 if ([super getObjectValue: anObject forString: string errorDescription: error])
186 return YES;
187
188 NSDate *date;
189 NSEnumerator *e = [tryFormatters objectEnumerator];
190 NSDateFormatter *tryFormatter;
191
192 // XXX untested; does this work?
193 while ( (tryFormatter = [e nextObject]) != nil) {
194 date = [tryFormatter dateFromString: string];
195 if (date != nil) goto success;
196 }
197
198 date = parse_natural_language_date(string);
199 if (date != nil) goto success;
200
201 return NO;
202
203success:
[21]204 *anObject = date;
[360]205 if (error != NULL) *error = nil;
[21]206 return YES;
207}
208
[360]209#pragma mark miscellaneous
210
211+ (BOOL)naturalLanguageParsingAvailable;
212{
213 return (my_perl != NULL);
214}
[21]215@end
Note: See TracBrowser for help on using the repository browser.