--- /dev/null
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#ifndef __Mailer_UIxMailFormatter_H__
+#define __Mailer_UIxMailFormatter_H__
+
+#import <Foundation/NSFormatter.h>
+
+@class NSString, NSCalendarDate, NSTimeZone;
+
+@interface UIxMailFormatter : NSFormatter
+{
+}
+
+/* labels */
+
+- (NSString *)labelForKey:(NSString *)_key;
+
+@end
+
+@interface UIxMailDateFormatter : UIxMailFormatter
+{
+ NSCalendarDate *now;
+ NSTimeZone *timeZone;
+ struct {
+ int showOnlyTimeForToday:1;
+ int showLabelsForNearDays:1; /* 'yesterday' instead of '2004-09-31' */
+ int reserved:30;
+ } dfFlags;
+}
+
+/* configuration */
+
+- (NSTimeZone *)timeZone;
+- (BOOL)showOnlyTimeForToday;
+- (BOOL)showLabelsForNearDays;
+
+@end
+
+@interface UIxSubjectFormatter : UIxMailFormatter
+{
+ unsigned maxLength;
+}
+
+/* configuration */
+
+- (unsigned int)maxLength;
+
+/* labels */
+
+- (NSString *)missingSubjectLabel;
+
+@end
+
+@interface UIxEnvelopeAddressFormatter : UIxMailFormatter
+@end
+
+#endif /* __Mailer_UIxMailFormatter_H__ */
--- /dev/null
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "UIxMailFormatter.h"
+#include "common.h"
+
+static Class StrClass = Nil;
+static Class CalDateClass = Nil;
+
+@implementation UIxMailFormatter
+
+static BOOL debugOn = YES;
+
++ (void)initialize {
+ StrClass = [NSString class];
+ CalDateClass = [NSCalendarDate class];
+}
+
+/* labels */
+
+- (NSString *)labelForKey:(NSString *)_key {
+ // TODO: fetch labels from context
+ return _key;
+}
+
+/* debugging */
+
+- (BOOL)isDebuggingEnabled {
+ return debugOn;
+}
+
+@end /* UIxMailFormatter */
+
+@implementation UIxMailDateFormatter
+
+- (id)init {
+ if ((self = [super init])) {
+ static NSTimeZone *met = nil;
+ if (met == nil) met = [[NSTimeZone timeZoneWithName:@"MET"] retain];
+
+ self->timeZone = [met retain];
+ self->dfFlags.showOnlyTimeForToday = 1;
+ self->dfFlags.showLabelsForNearDays = 1;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self->timeZone release];
+ [self->now release];
+ [super dealloc];
+}
+
+/* configuration */
+
+- (NSTimeZone *)timeZone {
+ return self->timeZone;
+}
+
+- (BOOL)showOnlyTimeForToday {
+ return self->dfFlags.showOnlyTimeForToday ? YES : NO;
+}
+- (BOOL)showLabelsForNearDays {
+ return self->dfFlags.showLabelsForNearDays ? YES : NO;
+}
+
+/* formatting dates */
+
+- (NSString *)stringForTime:(NSCalendarDate *)_d prefix:(unsigned char *)_p {
+ /* Note: prefix is not allowed to be long! */
+ unsigned char buf[32];
+
+ if (_p == NULL) _p = "";
+ sprintf(buf, "%s%02i:%02i", _p, [_d hourOfDay], [_d minuteOfHour]);
+ return [StrClass stringWithCString:buf];
+}
+
+- (NSString *)stringForCalendarDate:(NSCalendarDate *)_date {
+ unsigned char buf[32];
+
+ if (self->now == nil) {
+ self->now = [[NSCalendarDate alloc] init];
+ [self->now setTimeZone:[self timeZone]];
+ }
+ [_date setTimeZone:[self timeZone]];
+
+ if ([self showOnlyTimeForToday] && [_date isDateOnSameDay:self->now])
+ return [self stringForTime:_date prefix:NULL];
+
+ if ([self showLabelsForNearDays]) {
+ NSString *label;
+
+ if ([_date isDateOnSameDay:self->now])
+ label = [self labelForKey:@"today"];
+ else if ([_date isDateOnSameDay:[self->now yesterday]])
+ label = [self labelForKey:@"yesterday"];
+ else
+ label = nil;
+
+ if (label != nil) {
+ return [label stringByAppendingString:
+ [self stringForTime:_date prefix:", "]];
+ }
+ }
+
+ /* 26.08.2004 13:24 */
+ sprintf(buf, "%02d.%02d.%04d %02d:%02d",
+ [_date dayOfMonth], [_date monthOfYear], [_date yearOfCommonEra],
+ [_date hourOfDay], [_date minuteOfHour]);
+ return [StrClass stringWithCString:buf];
+}
+
+/* formatter entry function */
+
+- (NSString *)stringForObjectValue:(id)_date {
+ if (![_date isNotNull])
+ return nil;
+
+ if ([_date isKindOfClass:StrClass]) /* already formatted */
+ return _date;
+
+ if ([_date isKindOfClass:CalDateClass])
+ return [self stringForCalendarDate:_date];
+
+ [self debugWithFormat:
+ @"NOTE: unexpected object for date formatter: %@<%@>",
+ _date, NSStringFromClass([_date class])];
+ return [_date description];
+}
+
+@end /* UIxMailDateFormatter */
+
+@implementation UIxSubjectFormatter
+
+- (id)init {
+ if ((self = [super init])) {
+ self->maxLength = 64;
+ }
+ return self;
+}
+
+/* configuration */
+
+- (unsigned int)maxLength {
+ return self->maxLength;
+}
+
+/* labels */
+
+- (NSString *)missingSubjectLabel {
+ return [self labelForKey:@"no_subject"];
+}
+
+/* specific formatters */
+
+- (NSString *)stringForStringValue:(NSString *)_subject {
+ NSString *s;
+
+ if ([_subject hasPrefix:@"=?"]) { /* quoted printable */
+#warning TODO: work on QP decoding
+ /* =?iso-8859-1?q?Yannick=20DAmboise?= */
+ if ((s = [_subject stringByDecodingQuotedPrintable]))
+ _subject = s;
+ }
+
+ if ([_subject length] == 0)
+ return [self missingSubjectLabel];
+
+ if ([_subject length] <= [self maxLength])
+ return _subject;
+
+ s = [_subject substringToIndex:([self maxLength] - 3)];
+ return [s stringByAppendingString:@"..."];
+}
+
+- (NSString *)stringForDataValue:(NSData *)_subject {
+ NSString *s, *r;
+
+ if ([_subject length] == 0)
+ return [self missingSubjectLabel];
+
+ [self debugWithFormat:@"WARNING: NSData subject! (using UTF-8 to decode!)"];
+
+ // TODO: exception handler?
+ s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
+ if (s == nil) {
+ [self logWithFormat:@"ERROR: could do not decode NSData subject!"];
+ return [self labelForKey:@"Error_CouldNotDecodeSubject"];
+ }
+
+ r = [[self stringForStringValue:s] copy];
+ [s release];
+ return [r autorelease];
+}
+
+/* formatter entry function */
+
+- (NSString *)stringForObjectValue:(id)_subject {
+ if (![_subject isNotNull])
+ return [self missingSubjectLabel];
+
+ if ([_subject isKindOfClass:StrClass])
+ return [self stringForStringValue:_subject];
+ if ([_subject isKindOfClass:[NSData class]])
+ return [self stringForDataValue:_subject];
+
+ return [self stringForStringValue:[_subject stringValue]];
+}
+
+@end /* UIxSubjectFormatter */
+
+#include <NGImap4/NGImap4EnvelopeAddress.h>
+
+@implementation UIxEnvelopeAddressFormatter
+
+static Class EnvAddrClass = Nil;
+
++ (void)initialize {
+ if (EnvAddrClass == Nil) EnvAddrClass = [NGImap4EnvelopeAddress class];
+}
+
+/* configuration */
+
+- (unsigned)maxLength {
+ return 128; // TODO
+}
+
+- (NSString *)separator {
+ return @", ";
+}
+
+/* formatting envelope addresses */
+
+- (NSString *)stringForEnvelopeAddress:(NGImap4EnvelopeAddress *)_address {
+ NSString *s;
+
+ s = [_address personalName];
+ if ([s isNotNull]) return s;
+
+ s = [_address baseEMail];
+ if ([s isNotNull]) return s;
+
+ [self debugWithFormat:@"WARNING: unexpected envelope address: %@", _address];
+ return [_address stringValue];
+}
+
+- (NSString *)stringForArray:(NSArray *)_addresses {
+ NSMutableString *ms;
+ unsigned i, count;
+
+ if ((count = [_addresses count]) == 0)
+ return nil;
+
+ if (count == 1)
+ return [self stringForObjectValue:[_addresses objectAtIndex:0]];
+
+ ms = [NSMutableString stringWithCapacity:16 * count];
+ for (i = 0; i < count && [ms length] < [self maxLength]; i++) {
+ NSString *s;
+
+ s = [self stringForObjectValue:[_addresses objectAtIndex:i]];
+ if (s == nil)
+ continue;
+
+ if ([ms length] > 0) [ms appendString:[self separator]];
+ [ms appendString:s];
+ }
+ return ms;
+}
+
+/* formatter entry function */
+
+- (NSString *)stringForObjectValue:(id)_address {
+ if (![_address isNotNull])
+ return nil;
+
+ if ([_address isKindOfClass:StrClass]) /* preformatted? */
+ return _address;
+
+ if ([_address isKindOfClass:EnvAddrClass])
+ return [self stringForEnvelopeAddress:_address];
+
+ if ([_address isKindOfClass:[NSArray class]])
+ return [self stringForArray:_address];
+
+ [self debugWithFormat:
+ @"NOTE: unexpected object for envelope formatter: %@<%@>",
+ _address, NSStringFromClass([_address class])];
+ return [_address stringValue];
+}
+
+@end /* UIxEnvelopeAddressFormatter */