2004-10-05  Adam Fedor  <fedor@gnu.org>

	* configure.ac: Check for tzfile.h
	* NSTimeZone.m: Include system tzfile.h if found.
	(abbreviationMap): Add abbreviation from systemTimeZone if not
	already there.
	(systemTimeZone): Check for time zone in system localtime file.
	(getTimeZoneFile:): Look for file in system directory first.

Index: configure.ac
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/configure.ac,v
retrieving revision 1.54
diff -u -r1.54 configure.ac
--- configure.ac	27 Sep 2004 14:07:22 -0000	1.54
+++ configure.ac	1 Oct 2004 16:14:10 -0000
@@ -544,7 +544,7 @@
 #--------------------------------------------------------------------
 dnl AC_REPLACE_FUNCS(getrusage gettimeofday)
 
-AC_CHECK_HEADERS(time.h sys/time.h sys/rusage.h ucbinclude/sys/resource.h)
+AC_CHECK_HEADERS(time.h sys/time.h tzfile.h sys/rusage.h ucbinclude/sys/resource.h)
 AC_CHECK_FUNCS(time ctime tzset)
 
 #--------------------------------------------------------------------
Index: Headers/Additions/GNUstepBase/config.h.in
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Headers/Additions/GNUstepBase/config.h.in,v
retrieving revision 1.10
diff -u -r1.10 config.h.in
--- Headers/Additions/GNUstepBase/config.h.in	14 Jun 2004 22:27:20 -0000	1.10
+++ Headers/Additions/GNUstepBase/config.h.in	1 Oct 2004 16:14:10 -0000
@@ -303,6 +303,9 @@
 /* Define to 1 if you have the <time.h> header file. */
 #undef HAVE_TIME_H
 
+/* Define to 1 if you have the <tzfile.h> header file. */
+#undef HAVE_TZFILE_H
+
 /* Define to 1 if you have the `tzset' function. */
 #undef HAVE_TZSET
 
@@ -403,9 +406,11 @@
    first (like Motorola and SPARC, unlike Intel and VAX). */
 #undef WORDS_BIGENDIAN
 
-/* Define as `__inline' if that's what the C compiler calls it, or to nothing
-   if it is not supported. */
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
 #undef inline
+#endif
 
 /* Define to `unsigned' if <sys/types.h> does not define. */
 #undef size_t
Index: Source/NSTimeZone.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/NSTimeZone.m,v
retrieving revision 1.64
diff -u -r1.64 NSTimeZone.m
--- Source/NSTimeZone.m	1 Jul 2004 23:24:35 -0000	1.64
+++ Source/NSTimeZone.m	1 Oct 2004 16:14:11 -0000
@@ -27,10 +27,12 @@
    $Date: 2004/07/01 23:24:35 $ $Revision: 1.64 $
  */
   
-/* We use a implementation independent of the system, since POSIX
-   functions for time zones are woefully inadequate for implementing
-   NSTimeZone, and time zone names can be different from system to
-   system.
+/* Use the system time zones if available. In other cases, use an
+   implementation independent of the system, since POSIX functions for
+   time zones are woefully inadequate for implementing NSTimeZone.
+   Time zone names can be different from system to system, but usually
+   the user has already set up his timezone independant of GNUstep, so we
+   should respect that information.
 
    We do not use a dictionary for storing time zones, since such a
    dictionary would be VERY large (~500K).  And we would have to use a
@@ -43,8 +45,9 @@
     1) the user defaults database
     2) the GNUSTEP_TZ environment variable
     3) the file LOCAL_TIME_FILE in _time_zone_path()
-    4) the TZ environment variable
-    5) tzset() & tznam[] for platforms which have it
+    4) TZDEFAULT defined in tzfile.h on platforms which have it
+    5) the TZ environment variable ...OR...
+       tzset() & tznam[] for platforms which have it
     6) Windows registry, for Win32 systems
     7) or the fallback time zone (which is UTC)
    with the ones listed first having precedence.
@@ -66,16 +69,6 @@
    (file)      localtime {text; time zone eg Australia/Perth}
    (dir)       zones
 
-   Since NSTimeZone gets the name from LOCAL_TIME_FILE it's sufficient
-   to symlink this to the time zone name used elsewhere. For example:
-   Debian uses "/etc/timezone"
-
-   A number of POSIX systems have the zone files already installed.
-   For these systems it is sufficient to symlink ZONES_DIR to the
-   platform specific location.
-   For (g)libc6 this is /usr/share/zoneinfo
-   For Solaris  this is /usr/share/lib/zoneinfo
-
    Note that full zone info is required, especially the various "GMT"
    files which are created especially for OPENSTEP compatibility.
    Zone info comes from the Olson time database.
@@ -115,10 +108,12 @@
 #include "GNUstepBase/GSCategories.h"
 #include "GSConfig.h"
 
-
+#ifdef HAVE_TZFILE_H
+#include <tzfile.h>
+#else
 #define NOID
-#include "tzfile.h"
-
+#include "nstzfile.h"
+#endif
 
 /* Key for local time zone in user defaults. */
 #define LOCALDBKEY @"Local Time Zone"
@@ -899,15 +894,15 @@
 
 /**
  * <p>
- * The local time zone can be specified by:<br/ >
+ * The local time zone is obtained from, in order of preference:<br/ >
  *  1) the user defaults database: NSGlobalDomain "Local Time Zone"<br/ >
  *  2) the GNUSTEP_TZ environment variable<br/ >
  *  3) the file "localtime" in System/Library/Libraries/Resources/NSTimeZone<br/ >
- *  4) the TZ environment variable<br/ >
- *  5) tzset and tznam on platforms which have it<br/ >
+ *  4) The system zone settings (typically in /etc/localtime)<br/ >
+ *  5) the TZ environment variable OR<br/ >
+ *     tzset and tznam on platforms which have it<br/ >
  *  6) Windows registry, on Win32 systems<br/ >
  *  7) or the fallback time zone (which is UTC)<br/ >
- * with the ones listed first having precedence.
  * </p>
  * <p>If the GNUstep time zone datafiles become too out of date, one
  * can download an updated database from <uref
@@ -925,15 +920,10 @@
  * abbreviation and offsets from UTC are the same.
  * </p>
  * <p>The problems with depending on the OS for providing time zone
- * info are that some methods for the NSTimeZone classes might be
- * difficult to implement, and also that time zone names may vary
+ * info are that time zone names may vary
  * wildly between OSes (this could be a big problem when
  * archiving is used between different systems).
  * </p>
- * <p>On platforms where the zone info files are already installed
- * elsewhere it is sufficient to use a symlink provided the GMT+/-
- * zones are added.
- * </p>
  * <p>Win32:  Time zone names read from the registry are different
  * from other GNUstep installations. Be careful when moving data
  * between platforms in this case.
@@ -987,13 +977,27 @@
       a = [abbreviationDictionary objectForKey: the_abbrev];
       if (a == nil)
 	{
-	  a = [[NSMutableArray alloc] init];
+	  a = AUTORELEASE([NSMutableArray new]);
 	  [abbreviationDictionary setObject: a forKey: the_abbrev];
 	}
       [a addObject: the_name];
     }
   fclose(file);
 
+  /* Special case: Add the system time zone if it doesn't exist in the map */
+  {
+    id array;
+    id the_abbrev = [systemTimeZone abbreviation];
+    array = [abbreviationDictionary objectForKey: the_abbrev];
+    if (array == nil)
+      {
+	array = AUTORELEASE([NSMutableArray new]);
+	[abbreviationDictionary setObject: array forKey: the_abbrev];
+      }
+    if ([array containsObject: [systemTimeZone timeZoneName]] == nil)
+      [array addObject: [systemTimeZone timeZoneName]];
+  }
+
   return abbreviationDictionary;
 }
 
@@ -1204,6 +1208,29 @@
 	      localZoneString = [localZoneString stringByTrimmingSpaces];
 	    }
 	}
+#if defined(HAVE_TZFILE_H) && defined(TZDEFAULT)
+      if (localZoneString == nil)
+        {
+          /* Get the zone name from the localtime file, assuming the file
+	     is a symlink to the time zone. Getting the actual data (which
+	     is easier) doesn't help, since we won't know the name itself.  */
+	  NSString *tzdir = [NSString stringWithCString: TZDIR];
+	  localZoneString = [NSString stringWithCString: TZDEFAULT];
+	  localZoneString = [localZoneString stringByResolvingSymlinksInPath];
+	  if ( [localZoneString hasPrefix: tzdir] )
+	    {
+	      /* This must be the time zone name */
+	      localZoneString = [[localZoneString mutableCopy] autorelease];
+	      [(NSMutableString *)localZoneString deletePrefix: tzdir];
+	      if ( [localZoneString hasPrefix: @"/"] )
+	        {
+	          [(NSMutableString *)localZoneString deletePrefix: @"/"];
+	        }
+	    }
+	  else
+	    localZoneString = nil;
+        }
+#endif
 #if HAVE_TZSET
       /*
        * Try to get timezone from tzset and tzname
@@ -1254,6 +1281,7 @@
       
       if (localZoneString != nil)
 	{
+	  NSDebugLLog (@"NSTimeZone", @"Using zone %@", localZoneString);
 	  zone = [defaultPlaceholderTimeZone initWithName: localZoneString];
 	}
       else
@@ -1652,9 +1680,18 @@
  */
 + (NSString*) getTimeZoneFile: (NSString *)name
 {
-  NSString	*dir;
+  NSString	*dir = nil;
 
-  dir= _time_zone_path (ZONES_DIR);
+  /* Use the system zone info if possible, otherwise, use our installed 
+     info.  */
+#ifdef HAVE_TZFILE_H
+  dir = [NSString stringWithCString: TZDIR];
+  if ([[NSFileManager defaultManager] fileExistsAtPath:
+  	[dir stringByAppendingPathComponent: name]] == NO)
+    dir = nil;
+#endif
+  if (dir == nil)
+    dir= _time_zone_path (ZONES_DIR);
   return [dir stringByAppendingPathComponent: name];
 }
 
@@ -2167,11 +2204,13 @@
 	}
       header = (struct tzhead *)(bytes + pos);
       pos += sizeof(struct tzhead);
+#ifdef TZ_MAGIC
       if (memcmp(header->tzh_magic, TZ_MAGIC, strlen(TZ_MAGIC)) != 0)
 	{
 	  [NSException raise: fileException
 		      format: @"TZ_MAGIC is incorrect"];
 	}
+#endif
       n_trans = GSSwapBigI32ToHost(*(gss32*)header->tzh_timecnt);
       n_types = GSSwapBigI32ToHost(*(gss32*)header->tzh_typecnt);
       charcnt = GSSwapBigI32ToHost(*(gss32*)header->tzh_charcnt);
Index: Testing/nstimezone.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Testing/nstimezone.m,v
retrieving revision 1.7
diff -u -r1.7 nstimezone.m
--- Testing/nstimezone.m	23 Mar 2003 07:06:27 -0000	1.7
+++ Testing/nstimezone.m	1 Oct 2004 16:14:11 -0000
@@ -10,15 +10,18 @@
 int
 main ()
 {
-  id detail;
+  NSTimeZone *system;
   CREATE_AUTORELEASE_POOL(pool);
 
-  printf("time zones for PST:\n%s\n",
-[[[[NSTimeZone abbreviationMap] objectForKey: @"PST"] description] UTF8String]);
-  printf("time zones:\n%s\n",
-[[[NSTimeZone timeZoneArray] description] UTF8String]);
-  printf("local time zone:\n%s\n",
-[[[NSTimeZone localTimeZone] description] UTF8String]);
+  GSPrintf(stdout, @"System time zone\n");
+  system = [NSTimeZone systemTimeZone];
+  GSPrintf(stdout, @"  %@\n\n", [system description]);
+  
+  GSPrintf(stdout, @"Local time zone:\n  %@\n\n",
+	   [[NSTimeZone localTimeZone] description]);
+
+  GSPrintf(stdout, @"Time zones for PST:\n  %@\n",
+	   [[[NSTimeZone abbreviationMap] objectForKey: @"PST"] description]);
   RELEASE(pool);
   return 0;
 }
