]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1187 d1b88da0-ebda-0310...
authorfrancis <francis@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 11 Oct 2007 22:18:52 +0000 (22:18 +0000)
committerfrancis <francis@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 11 Oct 2007 22:18:52 +0000 (22:18 +0000)
20 files changed:
Main/GNUmakefile
OGoContentStore/GNUmakefile
SOPE/sope-patchset-r1544.diff [new file with mode: 0644]
SoObjects/Appointments/GNUmakefile
SoObjects/Contacts/GNUmakefile
SoObjects/Mailer/GNUmakefile
SoObjects/SOGo/GNUmakefile
UI/Common/GNUmakefile
UI/Contacts/GNUmakefile
UI/MailPartViewers/GNUmakefile
UI/MailerUI/GNUmakefile
UI/MainUI/GNUmakefile
UI/PreferencesUI/GNUmakefile
UI/Scheduler/GNUmakefile
UI/WebServerResources/browser_firefox.gif [new file with mode: 0644]
UI/WebServerResources/browser_ie.gif [new file with mode: 0644]
UI/WebServerResources/browser_safari.gif [new file with mode: 0644]
UI/WebServerResources/tablekit-trueresize.js [new file with mode: 0644]
UI/WebServerResources/tablekit.js [new file with mode: 0644]
sogo.spec [new file with mode: 0644]

index 9526d647a3fe9d44178231026b49cfecbc1cc591..f8113691beef38ac1ed56523571a2e3bfe226a82 100644 (file)
@@ -5,6 +5,9 @@ include $(GNUSTEP_MAKEFILES)/common.make
 include ../Version
 include ./Version
 
+ADDITIONAL_INCLUDE_DIRS += -I../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../SOPE/sope-gdl1/GDLContentStore/obj/
+
 SOGOD     = sogod-$(MAJOR_VERSION).$(MINOR_VERSION)
 TOOL_NAME = $(SOGOD)
 
index d66c95f2791026ad1339fab96821211ef5199555..d74e2646933b7fd6e98cf42c97ac242d163db1c5 100644 (file)
@@ -13,6 +13,9 @@ libOGoContentStore_HEADER_FILES_DIR         = .
 libOGoContentStore_HEADER_FILES_INSTALL_DIR = /OGoContentStore
 # no headers, commented out: FHS_HEADER_DIRS = OGoContentStore
 
+ADDITIONAL_INCLUDE_DIRS += -I../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../SOPE/sope-gdl1/GDLContentStore/obj/
+
 libOGoContentStore_OBJC_FILES +=               \
        iCalEntityObject+OCS.m                  \
        iCalRepeatableEntityObject+OCS.m        \
diff --git a/SOPE/sope-patchset-r1544.diff b/SOPE/sope-patchset-r1544.diff
new file mode 100644 (file)
index 0000000..5909c44
--- /dev/null
@@ -0,0 +1,435 @@
+Index: sope-mime/NGImap4/NGImap4Connection.m
+===================================================================
+--- sope-mime/NGImap4/NGImap4Connection.m      (revision 1544)
++++ sope-mime/NGImap4/NGImap4Connection.m      (working copy)
+@@ -381,7 +381,7 @@
+   
+   if (debugCache) [self logWithFormat:@"  no folders cached yet .."];
+   
+-  result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*")
++  result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"")
+                         pattern:@"*"];
+   if (![[result valueForKey:@"result"] boolValue]) {
+     [self errorWithFormat:@"Could not list mailbox hierarchy!"];
+Index: sope-mime/NGImap4/NGImap4ResponseParser.m
+===================================================================
+--- sope-mime/NGImap4/NGImap4ResponseParser.m  (revision 1544)
++++ sope-mime/NGImap4/NGImap4ResponseParser.m  (working copy)
+@@ -84,6 +84,8 @@
+ static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self,
+                                        BOOL isBodyStructure);
++static NSArray *_parseLanguages();
++
+ static NSString *_parseBodyString(NGImap4ResponseParser *self,
+                                   BOOL _convertString);
+ static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self,
+@@ -1627,6 +1629,29 @@
+   return _parseBodyDecodeString(self, _convertString, NO /* no decode */);
+ }
++static NSArray *_parseLanguages(NGImap4ResponseParser *self) {
++  NSMutableArray *languages;
++  NSString *language;
++
++  languages = [NSMutableArray array];
++  if (_la(self, 0) == '(') {
++    while (_la(self, 0) != ')') {
++      _consume(self,1);
++      language = _parseBodyString(self, YES);
++      if ([language length])
++      [languages addObject: language];
++    }
++    _consume(self,1);
++  }
++  else {
++    language = _parseBodyString(self, YES);
++    if ([language length])
++      [languages addObject: language];
++  }
++
++  return languages;
++}
++
+ static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self)
+ {
+   NSMutableDictionary *list;
+@@ -1734,10 +1759,11 @@
+                     *encoding, *bodysize;
+   NSDictionary        *parameterList;
+   NSMutableDictionary *dict;
++  NSArray           *languages;
+   type = [_parseBodyString(self, YES) lowercaseString];
+   _consumeIfMatch(self, ' ');
+-  subtype = _parseBodyString(self, YES);
++  subtype = [_parseBodyString(self, YES) lowercaseString];
+   _consumeIfMatch(self, ' ');
+   parameterList = _parseBodyParameterList(self);
+   _consumeIfMatch(self, ' ');
+@@ -1762,7 +1788,8 @@
+     _consumeIfMatch(self, ' ');
+     [dict setObject:_parseBodyString(self, YES) forKey:@"lines"];
+   }
+-  else if ([type isEqualToString:@"message"]) {
++  else if ([type isEqualToString:@"message"]
++         && [subtype isEqualToString:@"rfc822"]) {
+     if (_la(self, 0) != ')') {
+       _consumeIfMatch(self, ' ');
+       _consumeIfMatch(self, '(');
+@@ -1805,14 +1832,9 @@
+             forKey: @"disposition"];
+       if (_la(self, 0) != ')') {
+         _consume(self,1);
+-        if (_la(self, 0) == '(') {
+-          [dict setObject: _parseBodyParameterList(self)
+-                forKey: @"language"];
+-        }
+-        else {
+-          [dict setObject: _parseBodyString(self, YES)
+-                forKey: @"language"];
+-        }
++        languages = _parseLanguages(self);
++        if ([languages count])
++          [dict setObject: languages forKey: @"languages"];
+         if (_la(self, 0) != ')') {
+           _consume(self,1);
+           [dict setObject: _parseBodyString(self, YES)
+@@ -1829,6 +1851,7 @@
+ static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self,
+                                        BOOL isBodyStructure) {
+   NSMutableArray *parts;
++  NSArray      *languages;
+   NSString       *kind;
+   NSMutableDictionary *dict;
+@@ -1854,14 +1877,9 @@
+             forKey: @"disposition"];
+       if (_la(self, 0) != ')') {
+         _consume(self,1);
+-        if (_la(self, 0) == '(') {
+-          [dict setObject: _parseBodyParameterList(self)
+-                forKey: @"language"];
+-        }
+-        else {
+-          [dict setObject: _parseBodyString(self, YES)
+-                forKey: @"language"];
+-        }
++        languages = _parseLanguages(self);
++        if ([languages count])
++          [dict setObject: languages forKey: @"languages"];
+         if (_la(self, 0) != ')') {
+           _consume(self,1);
+           [dict setObject: _parseBodyString(self, YES)
+Index: sope-mime/NGMime/NGMimeBodyPart.m
+===================================================================
+--- sope-mime/NGMime/NGMimeBodyPart.m  (revision 1544)
++++ sope-mime/NGMime/NGMimeBodyPart.m  (working copy)
+@@ -31,18 +31,6 @@
+   return 2;
+ }
+-static NGMimeType *defaultType = nil;
+-
+-+ (void)initialize {
+-  static BOOL isInitialized = NO;
+-  if (!isInitialized) {
+-    isInitialized = YES;
+-    
+-    defaultType =
+-      [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain];
+-  }
+-}
+-  
+ + (id)bodyPartWithHeader:(NGHashMap *)_header {
+   return [[[self alloc] initWithHeader:_header] autorelease];
+ }
+@@ -156,13 +144,12 @@
+   if (!Fields)
+     Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames];
+   
+-  
+   type = [self->header objectForKey:Fields->contentType];
+   
+   if (![type isKindOfClass:[NGMimeType class]])
+     type = [NGMimeType mimeType:[type stringValue]];
+   
+-  return (type != nil ? type : (id)defaultType);
++  return type;
+ }
+ - (NSString *)contentId {
+Index: sope-mime/NGMime/NGMimeBodyParser.m
+===================================================================
+--- sope-mime/NGMime/NGMimeBodyParser.m        (revision 1544)
++++ sope-mime/NGMime/NGMimeBodyParser.m        (working copy)
+@@ -67,7 +67,10 @@
+   if (_data == nil) return nil;
+   
+   ctype = [_part contentType];
+-  
++  if (!ctype
++      && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)])
++    ctype = [_d parser: self contentTypeOfPart: _part];
++
+   if (![ctype isKindOfClass:[NGMimeType class]])
+     ctype = [NGMimeType mimeType:[ctype stringValue]];
+   
+Index: sope-mime/NGMime/NGMimePartParser.h
+===================================================================
+--- sope-mime/NGMime/NGMimePartParser.h        (revision 1544)
++++ sope-mime/NGMime/NGMimePartParser.h        (working copy)
+@@ -117,6 +117,7 @@
+     BOOL parserParseRawBodyDataOfPart:1;
+     BOOL parserBodyParserForPart:1;
+     BOOL parserDecodeBodyOfPart:1;
++    BOOL parserContentTypeOfPart:1;
+   } delegateRespondsTo;
+   
+@@ -275,6 +276,9 @@
+ - (id<NGMimeBodyParser>)parser:(NGMimePartParser *)_parser
+   bodyParserForPart:(id<NGMimePart>)_part;
++- (NGMimeType *)parser:(id)_parser
++  contentTypeOfPart:(id<NGMimePart>)_part;
++
+ @end /* NSObject(NGMimePartParserDelegate) */
+ @interface NSObject(NGMimePartParser)
+Index: sope-mime/NGMime/NGMimePartParser.m
+===================================================================
+--- sope-mime/NGMime/NGMimePartParser.m        (revision 1544)
++++ sope-mime/NGMime/NGMimePartParser.m        (working copy)
+@@ -1091,7 +1091,10 @@
+   id<NGMimeBodyParser> bodyParser   = nil;
+   
+   ctype = [_p contentType];
+-  
++  if (!ctype
++      && self->delegateRespondsTo.parserContentTypeOfPart)
++    ctype = [self->delegate parser: self contentTypeOfPart: _p];
++
+   contentType = ([ctype isKindOfClass:[NGMimeType class]])
+     ? ctype
+     : [NGMimeType mimeType:[ctype stringValue]];
+Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.h
+===================================================================
+--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.h (revision 1544)
++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.h (working copy)
+@@ -28,6 +28,7 @@
+ #define ___PostgreSQL72_Channel_H___
+ #include <GDLAccess/EOAdaptorChannel.h>
++#include <GDLContentStore/EOAdaptorChannel+GCS.h>
+ #include <libpq-fe.h>
+ @class NSArray, NSString, NSMutableDictionary;
+@@ -40,7 +41,7 @@
+   int        modification;
+ } PostgreSQL72FieldInfo;
+-@interface PostgreSQL72Channel : EOAdaptorChannel
++@interface PostgreSQL72Channel : EOAdaptorChannel <GCSEOAdaptorChannel>
+ {
+   // connection is valid after an openChannel call
+   PGConnection *connection;
+Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m
+===================================================================
+--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (revision 1544)
++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (working copy)
+@@ -713,6 +713,39 @@
+   return ms;
+ }
++/* GCSEOAdaptorChannel protocol */
++static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n"    \
++                                  @"  c_name VARCHAR (256) NOT NULL,\n"
++                                  @"  c_content VARCHAR (100000) NOT NULL,\n"
++                                  @"  c_creationdate INT4 NOT NULL,\n"
++                                  @"  c_lastmodified INT4 NOT NULL,\n"
++                                  @"  c_version INT4 NOT NULL,\n"
++                                  @"  c_deleted INT4 NULL\n"
++                                  @")");
++static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \
++                                     @"  c_uid VARCHAR (256) NOT NULL,\n"
++                                     @"  c_object VARCHAR (256) NOT NULL,\n"
++                                     @"  c_role VARCHAR (80) NOT NULL\n"
++                                     @")");
++
++- (NSException *) createGCSFolderTableWithName: (NSString *) tableName
++{
++  NSString *sql;
++
++  sql = [NSString stringWithFormat: sqlFolderFormat, tableName];
++
++  return [self evaluateExpressionX: sql];
++}
++
++- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName
++{
++  NSString *sql;
++
++  sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName];
++
++  return [self evaluateExpressionX: sql];
++}
++
+ @end /* PostgreSQL72Channel */
+ @implementation PostgreSQL72Channel(PrimaryKeyGeneration)
+Index: sope-appserver/NGObjWeb/GNUmakefile.postamble
+===================================================================
+--- sope-appserver/NGObjWeb/GNUmakefile.postamble      (revision 1544)
++++ sope-appserver/NGObjWeb/GNUmakefile.postamble      (working copy)
+@@ -23,14 +23,20 @@
+ # install makefiles
+-after-install ::
++after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make
++
++ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0)
++after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make
++endif
++
++$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make: ngobjweb.make
+       $(MKDIRS) $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/
+       $(INSTALL_DATA) ngobjweb.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make
+-ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0)
+-after-install ::
++$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make: woapp-gs.make
+       $(INSTALL_DATA) woapp-gs.make    \
+               $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make
++
++$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make: wobundle-gs.make
+       $(INSTALL_DATA) wobundle-gs.make \
+               $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make
+-endif
+Index: sope-appserver/NGObjWeb/WOContext.m
+===================================================================
+--- sope-appserver/NGObjWeb/WOContext.m        (revision 1544)
++++ sope-appserver/NGObjWeb/WOContext.m        (working copy)
+@@ -64,11 +64,13 @@
+ static BOOL     testNSURLs           = NO;
+ static BOOL     newCURLStyle         = NO;
+ static NSString *WOApplicationSuffix = nil;
++static NSURL    *redirectURL         = nil;
+ + (void)initialize {
+   static BOOL    didInit = NO;
+   NSUserDefaults *ud;
+   NSString       *cn;
++  NSString       *url;
+   if (didInit) return;
+@@ -91,6 +93,9 @@
+   debugCursor         = [ud boolForKey:@"WODebugCursor"] ? 1 : 0;
+   debugComponentAwake = [ud boolForKey:@"WODebugComponentAwake"];
+   WOApplicationSuffix = [[ud stringForKey:@"WOApplicationSuffix"] copy];
++  url                 = [ud stringForKey:@"WOApplicationRedirectURL"];
++  if (url != nil)
++    redirectURL       = [NSURL URLWithString: url];
+ }
+ + (id)contextWithRequest:(WORequest *)_r {
+@@ -503,6 +508,11 @@
+     return nil;
+   }
+   
++  if (redirectURL) {
++    // Use URL from user defaults (WOApplicationRedirectURL)
++    return redirectURL;
++  }
++  
+   if ((serverURL = [rq headerForKey:@"x-webobjects-server-url"]) == nil) {
+     if ((host = [rq headerForKey:@"host"]))
+       serverURL = [@"http://" stringByAppendingString:host];
+Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m
+===================================================================
+--- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m  (revision 1544)
++++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m  (working copy)
+@@ -216,6 +216,12 @@
+       assocCount++;
+     }
+   }
++  if (count > 0) {
++    if ((self->isAbsolute = OWGetProperty(_config, @"absolute"))) {
++      count--;
++      assocCount++;
++    }
++  }
+   
+   self->rest = _config;
+   
+Index: sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m
+===================================================================
+--- sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m      (revision 1544)
++++ sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m      (working copy)
+@@ -40,6 +40,7 @@
+   WOAssociation *string;
+   WOAssociation *target;
+   WOAssociation *disabled;
++  WOAssociation *isAbsolute;
+   WOElement     *template;
+   
+   /* new in WO4: */
+@@ -359,6 +360,7 @@
+ {
+   if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) {
+     self->href = _info->href;
++    self->isAbsolute = _info->isAbsolute;
+   }
+   return self;
+ }
+@@ -374,6 +376,9 @@
+   // TODO: we need a binding to disable rewriting!
+   NSRange  r;
+   
++  if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES)
++    return NO;
++
+   r = [_s rangeOfString:@":"];
+   if (r.length == 0) 
+     return YES;
+Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h
+===================================================================
+--- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h  (revision 1544)
++++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h  (working copy)
+@@ -41,7 +41,8 @@
+   WOAssociation *pageName;
+   WOAssociation *actionClass;
+   WOAssociation *directActionName;
+-  
++  WOAssociation *isAbsolute;
++
+   BOOL          sidInUrl;
+   /* 'ivar' associations */
+Index: sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m
+===================================================================
+--- sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m  (revision 1544)
++++ sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m  (working copy)
+@@ -31,6 +31,7 @@
+ #include <NGObjWeb/WOCookie.h>
+ #include <NGExtensions/NSData+gzip.h>
+ #include <NGHttp/NGHttp.h>
++#include <NGMime/NGMimeType.h>
+ #include "common.h"
+ #include <string.h>
+@@ -1016,6 +1017,12 @@
+ - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_header {
+ }
++- (NGMimeType *)parser:(id)_parser
++  contentTypeOfPart:(id<NGMimePart>)_part
++{
++  return [NGMimeType mimeType: @"text/plain; charset=utf-8"];
++}
++
+ @end /* WOHttpAdaptor */
+ @implementation WOCoreApplication(SimpleParserSelection)
index 0ae0a98f1b8298ca5e96252505815f4aaca7f649..6b51f6b46ff8ae625a10d89ebcb64691a9094599 100644 (file)
@@ -47,6 +47,9 @@ Appointments_COMPONENTS +=    \
        SOGoAptMailGermanRemoval.wo     \
        SOGoAptMailGermanDeletion.wo    \
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/wobundle.make
 -include GNUmakefile.postamble
index 3c1711c11c21bda43ae6d66790c71880d97bf6a9..a979a373a544ac6452db83cb0bb4a5d4d12a69ce 100644 (file)
@@ -19,6 +19,9 @@ Contacts_RESOURCE_FILES +=            \
        Version                         \
        product.plist                   \
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 2abb34c71ea9c7035af924d4f69d0c9aa26ebac2..cc04cf2583c26179e7ef31a2730dc70fef107e3d 100644 (file)
@@ -41,6 +41,9 @@ Mailer_RESOURCE_FILES += \
        SOGoMailFrenchForward.wo \
        SOGoMailGermanForward.wo
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/wobundle.make
 -include GNUmakefile.postamble
index d2b9d35688049d5d0240aebb9c20e0bf7c6ed54d..2530959f5011a6ccee3aaa94dfce6859c32fd657 100644 (file)
@@ -87,6 +87,8 @@ agenor_emails4uid_OBJC_FILES += agenor_emails4uid.m
 agenor_defaults_OBJC_FILES   += agenor_defaults.m
 
 ADDITIONAL_TOOL_LIBS += -Lobj -lSOGo$(LIBRARY_NAME_SUFFIX)
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
 
 -include GNUmakefile.preamble
 include ../common.make
index 80a1a5943a9e40729a78ce99442e1600eef9a4a3..e25a1ae1d57537366a4958cd97e9bf7b607d9ec5 100644 (file)
@@ -39,6 +39,9 @@ CommonUI_LOCALIZED_RESOURCE_FILES +=  \
 
 # make
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 34a2f8fc74836f4ce53be507a84b9d23b5d3337c..cb61ff5c5c881ff776639956a9e1d2d50c8c919c 100644 (file)
@@ -33,6 +33,9 @@ ContactsUI_LOCALIZED_RESOURCE_FILES +=        \
 
 # make
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index ae6a49d2459ae4754eb43b806be3bf419446dad4..dcfb3665ec05ef1489f9e222dce80da6ac8b6e8a 100644 (file)
@@ -40,6 +40,9 @@ MailPartViewers_LOCALIZED_RESOURCE_FILES += \
 
 # make
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 7a7c36b490f670212e268d05cdbe79e38355a24d..ba2c9579f02aac666d662fe9607b8fdf21c7aed2 100644 (file)
@@ -50,6 +50,9 @@ MailerUI_LOCALIZED_RESOURCE_FILES += \
 
 # make
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 83e84c1803de847f496cf349e8cab523f9e094d6..5bad0b55e61ff1ddb30a511a654def3e6f92ec83 100644 (file)
@@ -26,6 +26,9 @@ MainUI_RESOURCE_FILES +=      \
 MainUI_LOCALIZED_RESOURCE_FILES += \
        Locale Localizable.strings
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 2f8eaba0dcc283489f87d495ae437957701e7ff3..e3e70797548d286b4d9677846a8d35c10eadc9d9 100644 (file)
@@ -24,6 +24,9 @@ PreferencesUI_RESOURCE_FILES += \
 PreferencesUI_LOCALIZED_RESOURCE_FILES += \
        Localizable.strings             \
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
index 8c65e344b338e6b0389d9383d0e472a7407e37c1..7ef2b6158f445d3da695841a54ae2aae750d24e9 100644 (file)
@@ -66,6 +66,9 @@ SchedulerUI_RESOURCE_FILES +=         \
 
 # make
 
+ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/sope-gdl1/
+ADDITIONAL_LIB_DIRS += -L../../SOPE/sope-gdl1/GDLContentStore/obj/
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/bundle.make
 -include GNUmakefile.postamble
diff --git a/UI/WebServerResources/browser_firefox.gif b/UI/WebServerResources/browser_firefox.gif
new file mode 100644 (file)
index 0000000..d913404
Binary files /dev/null and b/UI/WebServerResources/browser_firefox.gif differ
diff --git a/UI/WebServerResources/browser_ie.gif b/UI/WebServerResources/browser_ie.gif
new file mode 100644 (file)
index 0000000..20f97ef
Binary files /dev/null and b/UI/WebServerResources/browser_ie.gif differ
diff --git a/UI/WebServerResources/browser_safari.gif b/UI/WebServerResources/browser_safari.gif
new file mode 100644 (file)
index 0000000..40d24fc
Binary files /dev/null and b/UI/WebServerResources/browser_safari.gif differ
diff --git a/UI/WebServerResources/tablekit-trueresize.js b/UI/WebServerResources/tablekit-trueresize.js
new file mode 100644 (file)
index 0000000..662ce5a
--- /dev/null
@@ -0,0 +1,101 @@
+/**\r
+ * This work is licensed under a Creative Commons Attribution 3.0 License\r
+ * (http://creativecommons.org/licenses/by/3.0/).\r
+ *\r
+ * You are free:\r
+ *    to Share - to copy, distribute and transmit the work\r
+ *    to Remix - to adapt the work\r
+ * Under the following conditions:\r
+ *    Attribution. You must attribute the work in the manner specified\r
+ *    by the author or licensor (but not in any way that suggests that\r
+ *    they endorse you or your use of the work).\r
+ *\r
+ * For any reuse or distribution, you must make clear to others the license\r
+ * terms of this work. The best way to do this is with a link to the\r
+ * Creative Commons web page.\r
+ *\r
+ * Any of the above conditions can be waived if you get permission from\r
+ * the copyright holder. Nothing in this license impairs or restricts\r
+ * the author's moral rights.\r
+ *\r
+ * Disclaimer\r
+ *\r
+ * Your fair dealing and other rights are in no way affected by the  above.\r
+ * This is a human-readable summary of the Legal Code (the full license).\r
+ *\r
+ * The author of this work is Vlad Bailescu (http://vlad.bailescu.ro). No\r
+ * warranty or support will be provided for this work, although updates\r
+ * might be made available at http://vlad.bailescu.ro/javascript/tablekit .\r
+ *\r
+ * Licence code and basic description provided by Creative Commons.\r
+ *\r
+ */\r
+Object.extend(TableKit.options || {}, {\r
+       // If true table width gets recalculated on column resize\r
+       trueResize : false,\r
+       // If true table width will be kept constant on column resize\r
+       keepWidth : false\r
+});\r
+       \r
+Object.extend(TableKit.Resizable, {\r
+       resize : function(table, index, w) {\r
+               // This part is taken from Andrew Tetlaw's original TableKit.Resizable.resize\r
+               var cell;\r
+               if(typeof index === 'number') {\r
+                       if(!table || (table.tagName && table.tagName !== "TABLE")) {return;}\r
+                       table = $(table);\r
+                       index = Math.min(table.rows[0].cells.length, index);\r
+                       index = Math.max(1, index);\r
+                       index -= 1;\r
+                       cell = (table.tHead && table.tHead.rows.length > 0) ? $(table.tHead.rows[table.tHead.rows.length-1].cells[index]) : $(table.rows[0].cells[index]);\r
+               } else {\r
+                       cell = $(index);\r
+                       table = table ? $(table) : cell.up('table');\r
+                       index = TableKit.getCellIndex(cell);\r
+               }\r
+               // And now, for the fun stuff\r
+               // Read the new options values for the given table\r
+               var op = TableKit.option('trueResize keepWidth minWidth', table.id);\r
+               // Took also the minWidth as we're gonna use it later anyway\r
+               var pad = parseInt(cell.getStyle('paddingLeft'),10) + parseInt(cell.getStyle('paddingRight'),10);\r
+               // Improvement: add cell border to padding as width incorporates both\r
+               pad += parseInt(cell.getStyle('borderLeftWidth'),10) + parseInt(cell.getStyle('borderRightWidth'),10);\r
+               w = Math.max(w-pad, op.minWidth); // This will also be used later\r
+               if (!op.trueResize) {\r
+                       // Original resize method\r
+                       cell.setStyle({'width' : w + 'px'});  // Using previously read minWidth instead of the old way\r
+               } else {\r
+                       // New stuff\r
+                       var delta = (w + pad - parseInt(cell.getWidth()));\r
+                       if (!op.keepWidth) {\r
+                               // We'll be updating the table width\r
+                               var tableWidth = parseInt(table.getWidth()) + delta;\r
+                               cell.setStyle({'width' : w + 'px'});\r
+                               table.setStyle({'width' : tableWidth + 'px'});\r
+                       } else {\r
+                               // Let's see what we have to do to keep the table width constant\r
+                               var cells = TableKit.getHeaderCells(table);\r
+                               if (index < 0 || index > cells.length) { return; }\r
+                               var nbour;\r
+                               if (index == cells.length - 1) {        // Rightmost cell\r
+                                       nbour = cells[index - 1];\r
+                               } else {        // Left or inner cell\r
+                                       nbour = cells[index + 1];\r
+                               }\r
+                               var nbourWidth = parseInt(nbour.getWidth());\r
+                               var nbourPad = parseInt(nbour.getStyle('paddingLeft'),10) + parseInt(nbour.getStyle('paddingRight'),10);\r
+                               var proposedNbourWidth = nbourWidth - nbourPad  - delta;\r
+                               var newNbourWidth;\r
+                               if (proposedNbourWidth < op.minWidth) {\r
+                                       // Don't be mean to neighbours. Step off their porch.\r
+                                       newNbourWidth = Math.min(nbourWidth - nbourPad, op.minWidth);\r
+                                       w -= newNbourWidth - proposedNbourWidth;\r
+                               } else {\r
+                                       newNbourWidth = proposedNbourWidth;\r
+                               }\r
+                               nbour.setStyle({'width' : newNbourWidth + 'px'});\r
+                               cell.setStyle({'width' : w + 'px'});\r
+                       }\r
+               }\r
+       }\r
+});
\ No newline at end of file
diff --git a/UI/WebServerResources/tablekit.js b/UI/WebServerResources/tablekit.js
new file mode 100644 (file)
index 0000000..cda8431
--- /dev/null
@@ -0,0 +1,858 @@
+/*\r
+*\r
+* Copyright (c) 2007 Andrew Tetlaw & Millstream Web Software\r
+* http://www.millstream.com.au/view/code/tablekit/\r
+* Version: 1.2.1 2007-03-11\r
+* \r
+* Permission is hereby granted, free of charge, to any person\r
+* obtaining a copy of this software and associated documentation\r
+* files (the "Software"), to deal in the Software without\r
+* restriction, including without limitation the rights to use, copy,\r
+* modify, merge, publish, distribute, sublicense, and/or sell copies\r
+* of the Software, and to permit persons to whom the Software is\r
+* furnished to do so, subject to the following conditions:\r
+* \r
+* The above copyright notice and this permission notice shall be\r
+* included in all copies or substantial portions of the Software.\r
+* \r
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+* SOFTWARE.\r
+* * \r
+*/\r
+\r
+// Use the TableKit class constructure if you'd prefer to init your tables as JS objects\r
+var TableKit = Class.create();\r
+\r
+TableKit.prototype = {\r
+       initialize : function(elm, options) {\r
+               var table = $(elm);\r
+               if(table.tagName !== "TABLE") {\r
+                       return;\r
+               }\r
+               TableKit.register(table,Object.extend(TableKit.options,options || {}));\r
+               this.id = table.id;\r
+               var op = TableKit.option('sortable resizable editable', this.id);\r
+               if(op.sortable) {\r
+                       TableKit.Sortable.init(table);\r
+               } \r
+               if(op.resizable) {\r
+                       TableKit.Resizable.init(table);\r
+               }\r
+               if(op.editable) {\r
+                       TableKit.Editable.init(table);\r
+               }\r
+       },\r
+       sort : function(column, order) {\r
+               TableKit.Sortable.sort(this.id, column, order);\r
+       },\r
+       resizeColumn : function(column, w) {\r
+               TableKit.Resizable.resize(this.id, column, w);\r
+       },\r
+       editCell : function(row, column) {\r
+               TableKit.Editable.editCell(this.id, row, column);\r
+       }\r
+};\r
+\r
+Object.extend(TableKit, {\r
+       getBodyRows : function(table) {\r
+               table = $(table);\r
+               var id = table.id;\r
+               if(!TableKit.rows[id]) {\r
+                       TableKit.rows[id] = (table.tHead && table.tHead.rows.length > 0) ? $A(table.tBodies[0].rows) : $A(table.rows).without(table.rows[0]);\r
+               }\r
+               return TableKit.rows[id];\r
+       },\r
+       getHeaderCells : function(table, cell) {\r
+               if(!table) { table = $(cell).up('table'); }\r
+               var id = table.id;\r
+               if(!TableKit.heads[id]) {\r
+                       //TableKit.heads[id] = $A((table.tHead && table.tHead.rows.length > 0) ? table.tHead.rows[table.tHead.rows.length-1].cells : table.rows[0].cells);\r
+                       TableKit.heads[id] = $A((table.tHead && table.tHead.rows.length > 0) ? table.tHead.rows[0].cells : table.rows[0].cells);\r
+               }\r
+               return TableKit.heads[id];\r
+       },\r
+       getCellIndex : function(cell) {\r
+               return $A(cell.parentNode.cells).indexOf(cell);\r
+       },\r
+       getRowIndex : function(row) {\r
+               return $A(row.parentNode.rows).indexOf(row);\r
+       },\r
+       getCellText : function(cell, refresh) {\r
+               if(!cell) { return ""; }\r
+               TableKit.registerCell(cell);\r
+               var data = TableKit.cells[cell.id];\r
+               if(refresh || data.refresh || !data.textContent) {\r
+                       data.textContent = cell.textContent ? cell.textContent : cell.innerText;\r
+                       data.refresh = false;\r
+               }\r
+               return data.textContent;\r
+       },\r
+       register : function(table, options) {\r
+               if(!table.id) {\r
+                       TableKit._tblcount += 1;\r
+                       table.id = "tablekit-table-" + TableKit._tblcount;\r
+               }\r
+               var id = table.id;\r
+               TableKit.tables[id] = TableKit.tables[id] ? Object.extend(TableKit.tables[id], options || {}) : Object.extend({sortable:false,resizable:false,editable:false}, options || {});\r
+       },\r
+       registerCell : function(cell) {\r
+               if(!cell.id) {\r
+                       TableKit._cellcount += 1;\r
+                       cell.id = "tablekit-cell-" + TableKit._cellcount;\r
+               }\r
+               if(!TableKit.cells[cell.id]) {\r
+                       TableKit.cells[cell.id] = {textContent : '', htmlContent : '', active : false};\r
+               }\r
+       },\r
+       isSortable : function(table) {\r
+               return TableKit.tables[table.id] ? TableKit.tables[table.id].sortable : false;\r
+       },\r
+       isResizable : function(table) {\r
+               return TableKit.tables[table.id] ? TableKit.tables[table.id].resizable : false;\r
+       },\r
+       isEditable : function(table) {\r
+               return TableKit.tables[table.id] ? TableKit.tables[table.id].editable : false;\r
+       },\r
+       setup : function(o) {\r
+               Object.extend(TableKit.options, o || {} );\r
+       },\r
+       option : function(s, id, o1, o2) {\r
+               o1 = o1 || TableKit.options;\r
+               o2 = o2 || (id ? (TableKit.tables[id] ? TableKit.tables[id] : {}) : {});\r
+               var key = id + s;\r
+               if(!TableKit._opcache[key]){\r
+                       TableKit._opcache[key] = $A($w(s)).inject([],function(a,v){\r
+                               a.push(a[v] = o2[v] || o1[v]);\r
+                               return a;\r
+                       });\r
+               }\r
+               return TableKit._opcache[key];\r
+       },\r
+       e : function(event) {\r
+               return event || window.event;\r
+       },\r
+       tables : {},\r
+       _opcache : {},\r
+       cells : {},\r
+       rows : {},\r
+       heads : {},\r
+       options : {\r
+               autoLoad : true,\r
+               stripe : true,\r
+               sortable : true,\r
+               resizable : true,\r
+               editable : true,\r
+               rowEvenClass : 'roweven',\r
+               rowOddClass : 'rowodd',\r
+               sortableSelector : ['table.sortable'],\r
+               columnClass : 'sortcol',\r
+               descendingClass : 'sortdesc',\r
+               ascendingClass : 'sortasc',\r
+               noSortClass : 'nosort',\r
+               sortFirstAscendingClass : 'sortfirstasc',\r
+               sortFirstDecendingClass : 'sortfirstdesc',\r
+               resizableSelector : ['table.resizable'],\r
+               minWidth : 10,\r
+               showHandle : true,\r
+               resizeOnHandleClass : 'resize-handle-active',\r
+               editableSelector : ['table.editable'],\r
+               formClassName : 'editable-cell-form',\r
+               noEditClass : 'noedit',\r
+               editAjaxURI : '/',\r
+               editAjaxOptions : {}\r
+       },\r
+       _tblcount : 0,\r
+       _cellcount : 0,\r
+       load : function() {\r
+               if(TableKit.options.autoLoad) {\r
+                       if(TableKit.options.sortable) {\r
+                               $A(TableKit.options.sortableSelector).each(function(s){\r
+                                       $$(s).each(function(t) {\r
+                                               TableKit.Sortable.init(t);\r
+                                       });\r
+                               });\r
+                       }\r
+                       if(TableKit.options.resizable) {\r
+                               $A(TableKit.options.resizableSelector).each(function(s){\r
+                                       $$(s).each(function(t) {\r
+                                               TableKit.Resizable.init(t);\r
+                                       });\r
+                               });\r
+                       }\r
+                       if(TableKit.options.editable) {\r
+                               $A(TableKit.options.editableSelector).each(function(s){\r
+                                       $$(s).each(function(t) {\r
+                                               TableKit.Editable.init(t);\r
+                                       });\r
+                               });\r
+                       }\r
+               }\r
+       }\r
+});\r
+\r
+TableKit.Rows = {\r
+       stripe : function(table) {\r
+               var rows = TableKit.getBodyRows(table);\r
+               rows.each(function(r,i) {\r
+                       TableKit.Rows.addStripeClass(table,r,i);\r
+               });\r
+       },\r
+       addStripeClass : function(t,r,i) {\r
+               t = t || r.up('table');\r
+               var op = TableKit.option('rowEvenClass rowOddClass', t.id);\r
+               var css = ((i+1)%2 === 0 ? op[0] : op[1]);\r
+               // using prototype's assClassName/RemoveClassName was not efficient for large tables, hence:\r
+               var cn = r.className.split(/\s+/);\r
+               var newCn = [];\r
+               for(var x = 0, l = cn.length; x < l; x += 1) {\r
+                       if(cn[x] !== op[0] && cn[x] !== op[1]) { newCn.push(cn[x]); }\r
+               }\r
+               newCn.push(css);\r
+               r.className = newCn.join(" ");\r
+       }\r
+};\r
+\r
+TableKit.Sortable = {\r
+       init : function(elm, options){\r
+               var table = $(elm);\r
+               if(table.tagName !== "TABLE") {\r
+                       return;\r
+               }\r
+               TableKit.register(table,Object.extend(options || {},{sortable:true}));\r
+               var sortFirst;\r
+               var cells = TableKit.getHeaderCells(table);\r
+               var op = TableKit.option('noSortClass columnClass sortFirstAscendingClass sortFirstDecendingClass', table.id);\r
+               cells.each(function(c){\r
+                       c = $(c);\r
+                       if(!c.hasClassName(op.noSortClass)) {\r
+                               Event.observe(c, 'mousedown', TableKit.Sortable._sort);\r
+                               c.addClassName(op.columnClass);\r
+                               if(c.hasClassName(op.sortFirstAscendingClass) || c.hasClassName(op.sortFirstDecendingClass)) {\r
+                                       sortFirst = c;\r
+                               }\r
+                       }\r
+               });\r
+\r
+               if(sortFirst) {\r
+                       if(sortFirst.hasClassName(op.sortFirstAscendingClass)) {\r
+                               TableKit.Sortable.sort(table, sortFirst, 1);\r
+                       } else {\r
+                               TableKit.Sortable.sort(table, sortFirst, -1);\r
+                       }\r
+               } else { // just add row stripe classes\r
+                       TableKit.Rows.stripe(table);\r
+               }\r
+       },\r
+       reload : function(table) {\r
+               table = $(table);\r
+               var cells = TableKit.getHeaderCells(table);\r
+               var op = TableKit.option('noSortClass columnClass', table.id);\r
+               cells.each(function(c){\r
+                       c = $(c);\r
+                       if(!c.hasClassName(op.noSortClass)) {\r
+                               Event.stopObserving(c, 'mousedown', TableKit.Sortable._sort);\r
+                               c.removeClassName(op.columnClass);\r
+                       }\r
+               });\r
+               TableKit.Sortable.init(table);\r
+       },\r
+       _sort : function(e) {\r
+               if(TableKit.Resizable._onHandle) {return;}\r
+               e = TableKit.e(e);\r
+               Event.stop(e);\r
+               var cell = Event.element(e);\r
+               while(!(cell.tagName && cell.tagName.match(/td|th/gi))) {\r
+                       cell = cell.parentNode;\r
+               }\r
+               TableKit.Sortable.sort(null, cell);\r
+       },\r
+       sort : function(table, index, order) {\r
+               var cell;\r
+               if(typeof index === 'number') {\r
+                       if(!table || (table.tagName && table.tagName !== "TABLE")) {\r
+                               return;\r
+                       }\r
+                       table = $(table);\r
+                       index = Math.min(table.rows[0].cells.length, index);\r
+                       index = Math.max(1, index);\r
+                       index -= 1;\r
+                       cell = (table.tHead && table.tHead.rows.length > 0) ? $(table.tHead.rows[table.tHead.rows.length-1].cells[index]) : $(table.rows[0].cells[index]);\r
+               } else {\r
+                       cell = $(index);\r
+                       table = table ? $(table) : cell.up('table');\r
+                       index = TableKit.getCellIndex(cell);\r
+               }\r
+               var op = TableKit.option('noSortClass descendingClass ascendingClass', table.id);\r
+               \r
+               if(cell.hasClassName(op.noSortClass)) {return;} \r
+               \r
+               order = order ? order : (cell.hasClassName(op.descendingClass) ? 1 : -1);\r
+               var rows = TableKit.getBodyRows(table);\r
+\r
+               if(cell.hasClassName(op.ascendingClass) || cell.hasClassName(op.descendingClass)) {\r
+                       rows.reverse(); // if it was already sorted we just need to reverse it.\r
+               } else {\r
+                       var datatype = TableKit.Sortable.getDataType(cell,index,table);\r
+                       var tkst = TableKit.Sortable.types;\r
+                       rows.sort(function(a,b) {\r
+                               return order * tkst[datatype].compare(TableKit.getCellText(a.cells[index]),TableKit.getCellText(b.cells[index]));\r
+                       });\r
+               }\r
+               var tb = table.tBodies[0];\r
+               var tkr = TableKit.Rows;\r
+               rows.each(function(r,i) {\r
+                       tb.appendChild(r);\r
+                       tkr.addStripeClass(table,r,i);\r
+               });\r
+               var hcells = TableKit.getHeaderCells(null, cell);\r
+               $A(hcells).each(function(c,i){\r
+                       c = $(c);\r
+                       c.removeClassName(op.ascendingClass);\r
+                       c.removeClassName(op.descendingClass);\r
+                       if(index === i) {\r
+                               if(order === 1) {\r
+                                       c.removeClassName(op.descendingClass);\r
+                                       c.addClassName(op.ascendingClass);\r
+                               } else {\r
+                                       c.removeClassName(op.ascendingClass);\r
+                                       c.addClassName(op.descendingClass);\r
+                               }\r
+                       }\r
+               });\r
+       },\r
+       types : {},\r
+       detectors : [],\r
+       addSortType : function() {\r
+               $A(arguments).each(function(o){\r
+                       TableKit.Sortable.types[o.name] = o;\r
+               });\r
+       },\r
+       getDataType : function(cell,index,table) {\r
+               cell = $(cell);\r
+               index = (index || index === 0) ? index : TableKit.getCellIndex(cell);\r
+               \r
+               var colcache = TableKit.Sortable._coltypecache;\r
+               var cache = colcache[table.id] ? colcache[table.id] : (colcache[table.id] = {});\r
+               \r
+               if(!cache[index]) {\r
+                       var t = '';\r
+                       // first look for a data type id on the heading row cell\r
+                       if(cell.id && TableKit.Sortable.types[cell.id]) {\r
+                               t = cell.id;\r
+                       }\r
+                       t = cell.classNames().detect(function(n){ // then look for a data type classname on the heading row cell\r
+                               return (TableKit.Sortable.types[n]) ? true : false;\r
+                       });\r
+                       if(!t) {\r
+                               var rows = TableKit.getBodyRows(table);\r
+                               cell = rows[0].cells[index]; // grab same index cell from body row to try and match data type\r
+                               t = TableKit.Sortable.detectors.detect(\r
+                                               function(d){\r
+                                                       return TableKit.Sortable.types[d].detect(TableKit.getCellText(cell));\r
+                                               });\r
+                       }\r
+                       cache[index] = t;\r
+               }\r
+               return cache[index];\r
+       },\r
+       _coltypecache : {}\r
+};\r
+\r
+TableKit.Sortable.detectors = $A($w('date-iso date date-eu date-au time currency datasize number casesensitivetext text')); // setting it here because Safari complained when I did it above...\r
+\r
+TableKit.Sortable.Type = Class.create();\r
+TableKit.Sortable.Type.prototype = {\r
+       initialize : function(name, options){\r
+               this.name = name;\r
+               options = Object.extend({\r
+                       normal : function(v){\r
+                               return v;\r
+                       },\r
+                       pattern : /.*/\r
+               }, options || {});\r
+               this.normal = options.normal;\r
+               this.pattern = options.pattern;\r
+               if(options.compare) {\r
+                       this.compare = options.compare;\r
+               }\r
+               if(options.detect) {\r
+                       this.detect = options.detect;\r
+               }\r
+       },\r
+       compare : function(a,b){\r
+               return TableKit.Sortable.Type.compare(this.normal(a), this.normal(b));\r
+       },\r
+       detect : function(v){\r
+               return this.pattern.test(v);\r
+       }\r
+};\r
+\r
+TableKit.Sortable.Type.compare = function(a,b) {\r
+       return a < b ? -1 : a === b ? 0 : 1;\r
+};\r
+\r
+TableKit.Sortable.addSortType(\r
+       new TableKit.Sortable.Type('number', {\r
+               pattern : /^[-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?/,\r
+               normal : function(v) {\r
+                       // This will grab the first thing that looks like a number from a string, so you can use it to order a column of various srings containing numbers.\r
+                       v = parseFloat(v.replace(/^.*?([-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?).*$/,"$1"));\r
+                       return isNaN(v) ? 0 : v;\r
+               }}),\r
+       new TableKit.Sortable.Type('text',{\r
+               normal : function(v) {\r
+                       return v ? v.toLowerCase() : '';\r
+               }}),\r
+       new TableKit.Sortable.Type('casesensitivetext',{pattern : /^[A-Z]+$/}),\r
+       new TableKit.Sortable.Type('datasize',{\r
+               pattern : /^[-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?\s?[k|m|g|t]b$/i,\r
+               normal : function(v) {\r
+                       var r = v.match(/^([-+]?[\d]*\.?[\d]+([eE][-+]?[\d]+)?)\s?([k|m|g|t]?b)?/i);\r
+                       var b = r[1] ? Number(r[1]).valueOf() : 0;\r
+                       var m = r[3] ? r[3].substr(0,1).toLowerCase() : '';\r
+                       var result = b;\r
+                       switch(m) {\r
+                               case  'k':\r
+                                       result = b * 1024;\r
+                                       break;\r
+                               case  'm':                              \r
+                                       result = b * 1024 * 1024;\r
+                                       break;\r
+                               case  'g':\r
+                                       result = b * 1024 * 1024 * 1024;\r
+                                       break;\r
+                               case  't':\r
+                                       result = b * 1024 * 1024 * 1024 * 1024;\r
+                                       break;\r
+                       }\r
+                       return result;\r
+               }}),\r
+       new TableKit.Sortable.Type('date-au',{\r
+               pattern : /^\d{2}\/\d{2}\/\d{4}\s?(?:\d{1,2}\:\d{2}(?:\:\d{2})?\s?[a|p]?m?)?/i,\r
+               normal : function(v) {\r
+                       if(!this.pattern.test(v)) {return 0;}\r
+                       var r = v.match(/^(\d{2})\/(\d{2})\/(\d{4})\s?(?:(\d{1,2})\:(\d{2})(?:\:(\d{2}))?\s?([a|p]?m?))?/i);\r
+                       var yr_num = r[3];\r
+                       var mo_num = parseInt(r[2],10)-1;\r
+                       var day_num = r[1];\r
+                       var hr_num = r[4] ? r[4] : 0;\r
+                       if(r[7] && r[7].toLowerCase().indexOf('p') !== -1) {\r
+                               hr_num = parseInt(r[4],10) + 12;\r
+                       }\r
+                       var min_num = r[5] ? r[5] : 0;\r
+                       var sec_num = r[6] ? r[6] : 0;\r
+                       return new Date(yr_num, mo_num, day_num, hr_num, min_num, sec_num, 0).valueOf();\r
+               }}),\r
+       new TableKit.Sortable.Type('date-us',{\r
+               pattern : /^\d{2}\/\d{2}\/\d{4}\s?(?:\d{1,2}\:\d{2}(?:\:\d{2})?\s?[a|p]?m?)?/i,\r
+               normal : function(v) {\r
+                       if(!this.pattern.test(v)) {return 0;}\r
+                       var r = v.match(/^(\d{2})\/(\d{2})\/(\d{4})\s?(?:(\d{1,2})\:(\d{2})(?:\:(\d{2}))?\s?([a|p]?m?))?/i);\r
+                       var yr_num = r[3];\r
+                       var mo_num = parseInt(r[1],10)-1;\r
+                       var day_num = r[2];\r
+                       var hr_num = r[4] ? r[4] : 0;\r
+                       if(r[7] && r[7].toLowerCase().indexOf('p') !== -1) {\r
+                               hr_num = parseInt(r[4],10) + 12;\r
+                       }\r
+                       var min_num = r[5] ? r[5] : 0;\r
+                       var sec_num = r[6] ? r[6] : 0;\r
+                       return new Date(yr_num, mo_num, day_num, hr_num, min_num, sec_num, 0).valueOf();\r
+               }}),\r
+       new TableKit.Sortable.Type('date-eu',{\r
+               pattern : /^\d{2}-\d{2}-\d{4}/i,\r
+               normal : function(v) {\r
+                       if(!this.pattern.test(v)) {return 0;}\r
+                       var r = v.match(/^(\d{2})-(\d{2})-(\d{4})/);\r
+                       var yr_num = r[3];\r
+                       var mo_num = parseInt(r[2],10)-1;\r
+                       var day_num = r[1];\r
+                       return new Date(yr_num, mo_num, day_num).valueOf();\r
+               }}),\r
+       new TableKit.Sortable.Type('date-iso',{\r
+               pattern : /[\d]{4}-[\d]{2}-[\d]{2}(?:T[\d]{2}\:[\d]{2}(?:\:[\d]{2}(?:\.[\d]+)?)?(Z|([-+][\d]{2}:[\d]{2})?)?)?/, // 2005-03-26T19:51:34Z\r
+               normal : function(v) {\r
+                       if(!this.pattern.test(v)) {return 0;}\r
+                   var d = v.match(/([\d]{4})(-([\d]{2})(-([\d]{2})(T([\d]{2}):([\d]{2})(:([\d]{2})(\.([\d]+))?)?(Z|(([-+])([\d]{2}):([\d]{2})))?)?)?)?/);             \r
+                   var offset = 0;\r
+                   var date = new Date(d[1], 0, 1);\r
+                   if (d[3]) { date.setMonth(d[3] - 1) ;}\r
+                   if (d[5]) { date.setDate(d[5]); }\r
+                   if (d[7]) { date.setHours(d[7]); }\r
+                   if (d[8]) { date.setMinutes(d[8]); }\r
+                   if (d[10]) { date.setSeconds(d[10]); }\r
+                   if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }\r
+                   if (d[14]) {\r
+                       offset = (Number(d[16]) * 60) + Number(d[17]);\r
+                       offset *= ((d[15] === '-') ? 1 : -1);\r
+                   }\r
+                   offset -= date.getTimezoneOffset();\r
+                   if(offset !== 0) {\r
+                       var time = (Number(date) + (offset * 60 * 1000));\r
+                       date.setTime(Number(time));\r
+                   }\r
+                       return date.valueOf();\r
+               }}),\r
+       new TableKit.Sortable.Type('date',{\r
+               pattern: /^(?:sun|mon|tue|wed|thu|fri|sat)\,\s\d{1,2}\s(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s\d{4}(?:\s\d{2}\:\d{2}(?:\:\d{2})?(?:\sGMT(?:[+-]\d{4})?)?)?/i, //Mon, 18 Dec 1995 17:28:35 GMT\r
+               compare : function(a,b) { // must be standard javascript date format\r
+                       if(a && b) {\r
+                               return TableKit.Sortable.Type.compare(new Date(a),new Date(b));\r
+                       } else {\r
+                               return TableKit.Sortable.Type.compare(a ? 1 : 0, b ? 1 : 0);\r
+                       }\r
+               }}),\r
+       new TableKit.Sortable.Type('time',{\r
+               pattern : /^\d{1,2}\:\d{2}(?:\:\d{2})?(?:\s[a|p]m)?$/i,\r
+               compare : function(a,b) {\r
+                       var d = new Date();\r
+                       var ds = d.getMonth() + "/" + d.getDate() + "/" + d.getFullYear() + " ";\r
+                       return TableKit.Sortable.Type.compare(new Date(ds + a),new Date(ds + b));\r
+               }}),\r
+       new TableKit.Sortable.Type('currency',{\r
+               pattern : /^[$£¥\80¤]/, // dollar,pound,yen,euro,generic currency symbol\r
+               normal : function(v) {\r
+                       return v ? parseFloat(v.replace(/[^-\d\.]/g,'')) : 0;\r
+               }})\r
+);\r
+\r
+TableKit.Resizable = {\r
+       init : function(elm, options){\r
+               var table = $(elm);\r
+               if(table.tagName !== "TABLE") {return;}\r
+               TableKit.register(table,Object.extend(options || {},{resizable:true}));          \r
+               var cells = TableKit.getHeaderCells(table);\r
+               cells.each(function(c){\r
+                       c = $(c);\r
+                       //log ("init on " + c.firstChild.nodeValue);\r
+                       Event.observe(c, 'mouseover', TableKit.Resizable.initDetect);\r
+                       Event.observe(c, 'mouseout', TableKit.Resizable.killDetect);\r
+               });\r
+       },\r
+       reload : function(table) {\r
+               table = $(table);\r
+               var cells = TableKit.getHeaderCells(table);\r
+               cells.each(function(c){\r
+                       c = $(c);\r
+                       Event.stopObserving(c, 'mouseover', TableKit.Resizable.initDetect);\r
+                       Event.stopObserving(c, 'mouseout', TableKit.Resizable.killDetect);\r
+               });\r
+               TableKit.Resizable.init(table);\r
+       },\r
+       resize : function(table, index, w) {\r
+               var cell;\r
+               if(typeof index === 'number') {\r
+                       if(!table || (table.tagName && table.tagName !== "TABLE")) {return;}\r
+                       table = $(table);\r
+                       index = Math.min(table.rows[0].cells.length, index);\r
+                       index = Math.max(1, index);\r
+                       index -= 1;\r
+                       cell = (table.tHead && table.tHead.rows.length > 0) ? $(table.tHead.rows[table.tHead.rows.length-1].cells[index]) : $(table.rows[0].cells[index]);\r
+               } else {\r
+                       cell = $(index);\r
+                       table = table ? $(table) : cell.up('table');\r
+                       index = TableKit.getCellIndex(cell);\r
+               }\r
+               var pad = parseInt(cell.getStyle('paddingLeft'),10) + parseInt(cell.getStyle('paddingRight'),10);\r
+               w = Math.max(w-pad, TableKit.option('minWidth', table.id)[0]);\r
+               cell.setStyle({'width' : w + 'px'});\r
+       },\r
+       initDetect : function(e) {\r
+               e = TableKit.e(e);\r
+               var cell = Event.element(e);\r
+               Event.observe(cell, 'mousemove', TableKit.Resizable.detectHandle);\r
+               Event.observe(cell, 'mousedown', TableKit.Resizable.startResize);\r
+       },\r
+       detectHandle : function(e) {\r
+               e = TableKit.e(e);\r
+               var cell = Event.element(e);\r
+               if(TableKit.Resizable.pointerPos(cell,Event.pointerX(e),Event.pointerY(e))){\r
+                       cell.addClassName(TableKit.option('resizeOnHandleClass', cell.up('table').id)[0]);\r
+                       TableKit.Resizable._onHandle = true;\r
+               } else {\r
+                       cell.removeClassName(TableKit.option('resizeOnHandleClass', cell.up('table').id)[0]);\r
+                       TableKit.Resizable._onHandle = false;\r
+               }\r
+       },\r
+       killDetect : function(e) {\r
+               e = TableKit.e(e);\r
+               TableKit.Resizable._onHandle = false;\r
+               var cell = Event.element(e);\r
+               if (!cell.tagName || cell.tagName != 'TD') return;\r
+               Event.stopObserving(cell, 'mousemove', TableKit.Resizable.detectHandle);\r
+               Event.stopObserving(cell, 'mousedown', TableKit.Resizable.startResize);\r
+               cell.removeClassName(TableKit.option('resizeOnHandleClass', cell.up('table').id)[0]);\r
+       },\r
+       startResize : function(e) {\r
+               e = TableKit.e(e);\r
+               if(!TableKit.Resizable._onHandle) { return;}\r
+               var cell = Event.element(e);\r
+               Event.stopObserving(cell, 'mousemove', TableKit.Resizable.detectHandle);\r
+               Event.stopObserving(cell, 'mousedown', TableKit.Resizable.startResize);\r
+               Event.stopObserving(cell, 'mouseout', TableKit.Resizable.killDetect);\r
+               TableKit.Resizable._cell = cell;\r
+               var table = cell.up('table');\r
+               TableKit.Resizable._tbl = table;\r
+               if(TableKit.option('showHandle', table.id)[0]) {\r
+                       TableKit.Resizable._handle = $(document.createElement('div')).addClassName('resize-handle').setStyle({\r
+                               'top' : Position.cumulativeOffset(cell)[1] + 'px',\r
+                               'left' : Event.pointerX(e) + 'px',\r
+                               'height' : table.getDimensions().height + 'px'\r
+                       });\r
+                       document.body.appendChild(TableKit.Resizable._handle);\r
+               }\r
+               Event.observe(document, 'mousemove', TableKit.Resizable.drag);\r
+               Event.observe(document, 'mouseup', TableKit.Resizable.endResize);\r
+               Event.stop(e);\r
+       },\r
+       endResize : function(e) {\r
+               e = TableKit.e(e);\r
+               var cell = TableKit.Resizable._cell;\r
+               TableKit.Resizable.resize(null, cell, (Event.pointerX(e) - Position.cumulativeOffset(cell)[0]));\r
+               Event.stopObserving(document, 'mousemove', TableKit.Resizable.drag);\r
+               Event.stopObserving(document, 'mouseup', TableKit.Resizable.endResize);\r
+               if(TableKit.option('showHandle', TableKit.Resizable._tbl.id)[0]) {\r
+                       $$('div.resize-handle').each(function(elm){\r
+                               document.body.removeChild(elm);\r
+                       });\r
+               }\r
+               Event.observe(cell, 'mouseout', TableKit.Resizable.killDetect);\r
+               TableKit.Resizable._tbl = TableKit.Resizable._handle = TableKit.Resizable._cell = null;\r
+               Event.stop(e);\r
+       },\r
+       drag : function(e) {\r
+               e = TableKit.e(e);\r
+               if(TableKit.Resizable._handle === null) {\r
+                       try {\r
+                               TableKit.Resizable.resize(TableKit.Resizable._tbl, TableKit.Resizable._cell, (Event.pointerX(e) - Position.cumulativeOffset(TableKit.Resizable._cell)[0]));\r
+                       } catch(e) {}\r
+               } else {\r
+                       TableKit.Resizable._handle.setStyle({'left' : Event.pointerX(e) + 'px'});\r
+               }\r
+               return false;\r
+       },\r
+       pointerPos : function(element, x, y) {\r
+       var offset = Position.cumulativeOffset(element);\r
+           return (y >= offset[1] &&\r
+                   y <  offset[1] + element.offsetHeight &&\r
+                   x >= offset[0] + element.offsetWidth - 5 &&\r
+                   x <  offset[0] + element.offsetWidth);\r
+       },\r
+       _onHandle : false,\r
+       _cell : null,\r
+       _tbl : null,\r
+       _handle : null\r
+};\r
+\r
+\r
+TableKit.Editable = {\r
+       init : function(elm, options){\r
+               var table = $(elm);\r
+               if(table.tagName !== "TABLE") {return;}\r
+               TableKit.register(table,Object.extend(options || {},{editable:true}));\r
+               Event.observe(table.tBodies[0], 'click', TableKit.Editable._editCell);\r
+       },\r
+       _editCell : function(e) {\r
+               e = TableKit.e(e);\r
+               var cell = Event.findElement(e,'td');\r
+               TableKit.Editable.editCell(null, cell);\r
+       },\r
+       editCell : function(table, index, cindex) {\r
+               var cell, row;\r
+               if(typeof index === 'number') {\r
+                       if(!table || (table.tagName && table.tagName !== "TABLE")) {return;}\r
+                       table = $(table);\r
+                       index = Math.min(table.tBodies[0].rows.length, index);\r
+                       index = Math.max(1, index);\r
+                       index -= 1;\r
+                       cindex = Math.min(table.rows[0].cells.length, cindex);\r
+                       cindex = Math.max(1, cindex);\r
+                       cindex -= 1;\r
+                       row = $(table.tBodies[0].rows[index]);\r
+                       cell = $(row.cells[cindex]);\r
+               } else {\r
+                       cell = $(index);\r
+                       table = (table && table.tagName && table.tagName !== "TABLE") ? $(table) : cell.up('table');\r
+                       row = cell.up('tr');\r
+               }\r
+               var op = TableKit.option('noEditClass', table.id);\r
+               if(cell.hasClassName(op.noEditClass)) {return;}\r
+               \r
+               var head = $(TableKit.getHeaderCells(table, cell)[TableKit.getCellIndex(cell)]);\r
+               if(head.hasClassName(op.noEditClass)) {return;}\r
+               \r
+               TableKit.registerCell(cell);\r
+               var data = TableKit.cells[cell.id];\r
+               if(data.active) {return;}\r
+               data.htmlContent = cell.innerHTML;\r
+               var ftype = TableKit.Editable.types['text-input'];\r
+               if(head.id && TableKit.Editable.types[head.id]) {\r
+                       ftype = TableKit.Editable.types[head.id];\r
+               } else {\r
+                       var n = head.classNames().detect(function(n){\r
+                                       return (TableKit.Editable.types[n]) ? true : false;\r
+                       });\r
+                       ftype = n ? TableKit.Editable.types[n] : ftype;\r
+               }\r
+               ftype.edit(cell);\r
+               data.active = true;\r
+       },\r
+       types : {},\r
+       addCellEditor : function(o) {\r
+               if(o && o.name) { TableKit.Editable.types[o.name] = o; }\r
+       }\r
+};\r
+\r
+TableKit.Editable.CellEditor = Class.create();\r
+TableKit.Editable.CellEditor.prototype = {\r
+       initialize : function(name, options){\r
+               this.name = name;\r
+               this.options = Object.extend({\r
+                       element : 'input',\r
+                       attributes : {name : 'value', type : 'text'},\r
+                       selectOptions : [],\r
+                       showSubmit : true,\r
+                       submitText : 'OK',\r
+                       showCancel : true,\r
+                       cancelText : 'Cancel',\r
+                       ajaxURI : null,\r
+                       ajaxOptions : null\r
+               }, options || {});\r
+       },\r
+       edit : function(cell) {\r
+               cell = $(cell);\r
+               var op = this.options;\r
+               var table = cell.up('table');\r
+               \r
+               var form = $(document.createElement("form"));\r
+               form.id = cell.id + '-form';\r
+               form.addClassName(TableKit.option('formClassName', table.id)[0]);\r
+               form.onsubmit = this._submit.bindAsEventListener(this);\r
+               \r
+               var field = document.createElement(op.element);\r
+                       $H(op.attributes).each(function(v){\r
+                               field[v.key] = v.value;\r
+                       });\r
+                       switch(op.element) {\r
+                               case 'input':\r
+                               case 'textarea':\r
+                               field.value = TableKit.getCellText(cell);\r
+                               break;\r
+                               \r
+                               case 'select':\r
+                               var txt = TableKit.getCellText(cell);\r
+                               $A(op.selectOptions).each(function(v){\r
+                                       field.options[field.options.length] = new Option(v[0], v[1]);\r
+                                       if(txt === v[1]) {\r
+                                               field.options[field.options.length-1].selected = 'selected';\r
+                                       }\r
+                               });\r
+                               break;\r
+                       }\r
+                       form.appendChild(field);\r
+                       if(op.element === 'textarea') {\r
+                               form.appendChild(document.createElement("br"));\r
+                       }\r
+                       if(op.showSubmit) {\r
+                               var okButton = document.createElement("input");\r
+                               okButton.type = "submit";\r
+                               okButton.value = op.submitText;\r
+                               okButton.className = 'editor_ok_button';\r
+                               form.appendChild(okButton);\r
+                       }\r
+                       if(op.showCancel) {\r
+                               var cancelLink = document.createElement("a");\r
+                               cancelLink.href = "#";\r
+                               cancelLink.appendChild(document.createTextNode(op.cancelText));\r
+                               cancelLink.onclick = this._cancel.bindAsEventListener(this);\r
+                               cancelLink.className = 'editor_cancel';      \r
+                               form.appendChild(cancelLink);\r
+                       }\r
+                       cell.innerHTML = '';\r
+                       cell.appendChild(form);\r
+       },\r
+       _submit : function(e) {\r
+               var cell = Event.findElement(e,'td');\r
+               var form = Event.findElement(e,'form');\r
+               Event.stop(e);\r
+               this.submit(cell,form);\r
+       },\r
+       submit : function(cell, form) {\r
+               var op = this.options;\r
+               form = form ? form : cell.down('form');\r
+               var head = $(TableKit.getHeaderCells(null, cell)[TableKit.getCellIndex(cell)]);\r
+               var row = cell.up('tr');\r
+               var table = cell.up('table');\r
+               var s = '&row=' + (TableKit.getRowIndex(row)+1) + '&cell=' + (TableKit.getCellIndex(cell)+1) + '&id=' + row.id + '&field=' + head.id + '&' + Form.serialize(form);\r
+               this.ajax = new Ajax.Updater(cell, op.ajaxURI || TableKit.option('editAjaxURI', table.id)[0], Object.extend(op.ajaxOptions || TableKit.option('editAjaxOptions', table.id)[0], {\r
+                       postBody : s,\r
+                       onComplete : function() {\r
+                               var data = TableKit.cells[cell.id];\r
+                               data.active = false;\r
+                               data.refresh = true; // mark cell cache for refreshing, in case cell contents has changed and sorting is applied\r
+                       }\r
+               }));\r
+       },\r
+       _cancel : function(e) {\r
+               var cell = Event.findElement(e,'td');\r
+               Event.stop(e);\r
+               this.cancel(cell);\r
+       },\r
+       cancel : function(cell) {\r
+               this.ajax = null;\r
+               var data = TableKit.cells[cell.id];\r
+               cell.innerHTML = data.htmlContent;\r
+               data.htmlContent = '';\r
+               data.active = false;\r
+       },\r
+       ajax : null\r
+};\r
+\r
+TableKit.Editable.textInput = function(n,attributes) {\r
+       TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {\r
+               element : 'input',\r
+               attributes : Object.extend({name : 'value', type : 'text'}, attributes||{})\r
+       }));\r
+};\r
+TableKit.Editable.textInput('text-input');\r
+\r
+TableKit.Editable.multiLineInput = function(n,attributes) {\r
+       TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {\r
+               element : 'textarea',\r
+               attributes : Object.extend({name : 'value', rows : '5', cols : '20'}, attributes||{})\r
+       }));    \r
+};     \r
+TableKit.Editable.multiLineInput('multi-line-input');\r
+\r
+TableKit.Editable.selectInput = function(n,attributes,selectOptions) {\r
+       TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {\r
+               element : 'select',\r
+               attributes : Object.extend({name : 'value'}, attributes||{}),\r
+               'selectOptions' : selectOptions\r
+       }));    \r
+};\r
+\r
+/*\r
+TableKit.Bench = {\r
+       bench : [],\r
+       start : function(){\r
+               TableKit.Bench.bench[0] = new Date().getTime();\r
+       },\r
+       end : function(s){\r
+               TableKit.Bench.bench[1] = new Date().getTime();\r
+               alert(s + ' ' + ((TableKit.Bench.bench[1]-TableKit.Bench.bench[0])/1000)+' seconds.') //console.log(s + ' ' + ((TableKit.Bench.bench[1]-TableKit.Bench.bench[0])/1000)+' seconds.')\r
+               TableKit.Bench.bench = [];\r
+       }\r
+} */\r
+\r
+if(window.FastInit) {\r
+       FastInit.addOnLoad(TableKit.load);\r
+} else {\r
+       Event.observe(window, 'load', TableKit.load);\r
+}\r
diff --git a/sogo.spec b/sogo.spec
new file mode 100644 (file)
index 0000000..9ce2f71
--- /dev/null
+++ b/sogo.spec
@@ -0,0 +1,185 @@
+%define lfmaj 1
+%define lfmin 1
+
+Summary:      Scalable OpenGroupware.org (Inverse edition)
+Name:         sogo
+Version:      %{sogo_version}.%{sogo_release}
+Release:      gnustep.%{dist_suffix}
+Vendor:       http://www.inverse.ca/
+Packager:     Wolfgang Sourdeau <wsourdeau@inverse.ca>
+License:      GPL
+URL:          http://www.inverse.ca/contributions/sogo.html
+Group:        Productivity/Groupware
+Source:       %{sogo_source}
+Prefix:       %{sogo_prefix}
+AutoReqProv:  off
+Requires:     gnustep-base sope%{sope_major_version}%{sope_minor_version}-core httpd mod_ngobjweb sope%{sope_major_version}%{sope_minor_version}-cards
+BuildRoot:    %{_tmppath}/%{name}-%{version}-%{release}
+BuildPreReq:  gcc-objc gnustep-base gnustep-make sope%{sope_major_version}%{sope_minor_version}-appserver-devel sope%{sope_major_version}%{sope_minor_version}-core-devel sope%{sope_major_version}%{sope_minor_version}-ldap-devel sope%{sope_major_version}%{sope_minor_version}-mime-devel sope%{sope_major_version}%{sope_minor_version}-xml-devel sope%{sope_major_version}%{sope_minor_version}-gdl1-devel sope%{sope_major_version}%{sope_minor_version}-cards-devel
+
+%description
+SOGo is a groupware server built around OpenGroupware.org (OGo) and
+the SOPE application server.  It focuses on scalability.
+
+The Inverse edition of this project has many feature enhancements:
+- CalDAV and GroupDAV compliance
+- full handling of vCard as well as vCalendar/iCalendar formats
+- support for folder sharing and ACLs
+
+The Web interface has been rewritten in an AJAX fashion to provided a faster
+UI for the users, consistency in look and feel with the Mozilla applications,
+and to reduce the load of the transactions on the server.
+
+%package -n sogo-devel
+Summary:      Development headers and libraries for SOGo
+Group:        Development/Libraries/Objective C
+AutoReqProv:  off
+
+%description -n sogo-devel
+Development headers and libraries for SOGo. Needed to create modules.
+
+%package -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore
+Summary:      Storage backend for folder abstraction.
+Group:        Development/Libraries/Objective C
+Requires:     sope%{sope_major_version}%{sope_minor_version}-gdl1
+AutoReqProv:  off
+
+%description -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore
+The storage backend implements the "low level" folder abstraction, which is
+basically an arbitary "BLOB" containing some document.
+
+SOPE is a framework for developing web applications and services. The
+name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE.
+
+%package -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore-devel
+Summary:      Development files for the GNUstep database libraries
+Group:        Development/Libraries/Objective C
+Requires:     sope%{sope_major_version}%{sope_minor_version}-gdl1
+AutoReqProv:  off
+
+%description -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore-devel
+This package contains the header files for SOPE's GDLContentStore library.
+
+SOPE is a framework for developing web applications and services. The
+name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE.
+
+
+%package -n sope%{sope_major_version}%{sope_minor_version}-gdl1-tools
+Summary:      Tools (gcs_cat/gcs_gensql/gcs_ls/gcs_mkdir/gcs_recreatequick)
+Group:        Development/Libraries/Objective C
+Requires:     sope%{sope_major_version}%{sope_minor_version}-gdl1
+AutoReqProv:  off
+
+%description -n sope%{sope_major_version}%{sope_minor_version}-gdl1-tools
+Various tools around the GDLContentStore.
+
+SOPE is a framework for developing web applications and services. The
+name "SOPE" (SKYRiX Object Publishing Environment) is inspired by ZOPE.
+
+########################################
+%prep
+rm -fr ${RPM_BUILD_ROOT}
+%setup -q -n sogo
+
+# ****************************** build ********************************
+%build
+. /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
+./configure \
+            --enable-strip \
+            --disable-debug \
+           --with-gnustep
+
+make
+
+# ****************************** install ******************************
+%install
+make INSTALL_ROOT_DIR=${RPM_BUILD_ROOT} \
+     GNUSTEP_INSTALLATION_DIR=${RPM_BUILD_ROOT}%{prefix} \
+     install
+cp -a UI/WebServerResources UI/Templates ${RPM_BUILD_ROOT}%{prefix}/Library/SOGo-%{sogo_version}
+mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
+mkdir -p ${RPM_BUILD_ROOT}/etc/httpd/conf.d
+mkdir -p ${RPM_BUILD_ROOT}/usr/sbin
+mkdir -p ${RPM_BUILD_ROOT}/var/run/sogo
+mkdir -p ${RPM_BUILD_ROOT}/var/log/sogo
+cp Apache/SOGo.conf ${RPM_BUILD_ROOT}/etc/httpd/conf.d/
+cp Scripts/sogo-init.d-rhel4 ${RPM_BUILD_ROOT}/etc/init.d/sogod
+cp Scripts/sogod-redhat ${RPM_BUILD_ROOT}/usr/sbin/sogod
+rm -rf ${RPM_BUILD_ROOT}%{prefix}/Tools/test_quick_extract
+rm -rf ${RPM_BUILD_ROOT}%{prefix}/Library/Headers/NGCards
+rm -rf ${RPM_BUILD_ROOT}%{prefix}/Library/Libraries/libNGCards.*
+rm -rf ${RPM_BUILD_ROOT}%{prefix}/Library/SaxDrivers-%{sope_major_version}.%{sope_minor_version}
+rm -rf ${RPM_BUILD_ROOT}%{prefix}/Library/SaxMappings
+
+# ****************************** clean ********************************
+%clean
+rm -fr ${RPM_BUILD_ROOT}
+
+# ****************************** files ********************************
+%files -n sogo
+%defattr(-,root,root,-)
+
+/etc/init.d/sogod
+/etc/httpd/conf.d/SOGo.conf
+/usr/sbin/sogod
+/var/run/sogo
+/var/log/sogo
+%{prefix}/Tools/sogod-0.9
+%{prefix}/Library/Libraries/libSOGo.so.*
+%{prefix}/Library/Libraries/libSOGoUI.so.*
+%{prefix}/Library/Libraries/libOGoContentStore.so*
+%{prefix}/Library/SOGo-%{sogo_version}/*.SOGo
+%{prefix}/Library/SOGo-%{sogo_version}/Templates
+%{prefix}/Library/SOGo-%{sogo_version}/WebServerResources
+%{prefix}/Library/OCSTypeModels/appointment.ocs
+%{prefix}/Library/OCSTypeModels/contact.ocs
+%{prefix}/Library/OCSTypeModels/appointment-oracle.ocs
+%{prefix}/Library/OCSTypeModels/contact-oracle.ocs
+%{prefix}/Library/WOxElemBuilders-%{sope_version}/SOGoElements.wox
+
+%doc ChangeLog README NEWS Scripts/sql-update-20070724.sh Scripts/sql-update-20070822.sh
+
+%files -n sogo-devel
+%{prefix}/Library/Headers/SOGo
+%{prefix}/Library/Headers/SOGoUI
+%{prefix}/Library/Libraries/libSOGo.so
+%{prefix}/Library/Libraries/libSOGoUI.so
+
+%files -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore
+%defattr(-,root,root,-)
+%{prefix}/Library/Libraries/libGDLContentStore*.so.%{sope_version}*
+
+%files -n sope%{sope_major_version}%{sope_minor_version}-gdl1-contentstore-devel
+%{prefix}/Library/Headers/GDLContentStore
+%{prefix}/Library/Libraries/libGDLContentStore*.so
+
+%files -n sope%{sope_major_version}%{sope_minor_version}-gdl1-tools
+%defattr(-,root,root,-)
+%{prefix}/Tools/gcs_cat
+%{prefix}/Tools/gcs_gensql
+%{prefix}/Tools/gcs_ls
+%{prefix}/Tools/gcs_mkdir
+%{prefix}/Tools/gcs_recreatequick
+
+# **************************** pkgscripts *****************************
+%post
+if ! id sogo >& /dev/null; then /usr/sbin/adduser sogo; fi
+/bin/chown sogo /var/run/sogo
+/bin/chown sogo /var/log/sogo
+
+%postun
+if test "$1" = "0"
+then
+  /usr/sbin/userdel sogo
+  /usr/sbin/groupdel sogo
+  /bin/rm -rf /var/run/sogo
+fi
+
+# ********************************* changelog *************************
+%changelog
+* Tue Oct 4 2007 Francis Lachapelle <flachapelle@inverse.ca>
+- added package sope-gdl1-contentstore
+
+* Wed Jul 18 2007 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+- initial build
+