[sword-cvs] icu-sword/source/i18n astro.cpp,NONE,1.1 astro.h,NONE,1.1 chnsecal.cpp,NONE,1.1 chnsecal.h,NONE,1.1 digitlst.cpp,NONE,1.1 digitlst.h,NONE,1.1 gregoimp.cpp,NONE,1.1 gregoimp.h,NONE,1.1 hebrwcal.cpp,NONE,1.1 hebrwcal.h,NONE,1.1 i18n.vcproj.old,NONE,1.1 islamcal.cpp,NONE,1.1 islamcal.h,NONE,1.1 olsontz.cpp,NONE,1.1 olsontz.h,NONE,1.1 ucurrimp.h,NONE,1.1 ulocdata.c,NONE,1.1 Makefile.in,1.5,1.6 anytrans.cpp,1.1,1.2 anytrans.h,1.1,1.2 buddhcal.cpp,1.1,1.2 buddhcal.h,1.1,1.2 calendar.cpp,1.3,1.4 choicfmt.cpp,1.4,1.5 coleitr.cpp,1.3,1.4 coll.cpp,1.4,1.5 cpdtrans.cpp,1.4,1.5 cpdtrans.h,1.1,1.2 datefmt.cpp,1.3,1.4 dcfmtsym.cpp,1.3,1.4 decimfmt.cpp,1.6,1.7 dtfmtsym.cpp,1.4,1.5 esctrn.cpp,1.3,1.4 esctrn.h,1.3,1.4 fmtable.cpp,1.3,1.4 format.cpp,1.3,1.4 funcrepl.cpp,1.1,1.2 funcrepl.h,1.1,1.2 gregocal.cpp,1.3,1.4 hextouni.cpp,1.4,1.5 hextouni.h,1.1,1.2 i18n.dsp,1.5,1.6 i18n.rc,1.3,1.4 i18n.vcproj,1.1,1.2 japancal.cpp,1.1,1.2 japancal.h,1.1,1.2 msgfmt.cpp,1.4,1.5 name2uni.cpp,1.4,1.5 name2uni.h,1.3,1.4 nfrs.cpp,1.5,1.6 nfrule.cpp,1.5,1.6 nfsubs.cpp,1.5,1.6 nortrans.cpp,1.5,1.6 nortrans.h,1.3,1.4 nultrans.cpp,1.3,1.4 nultrans.h,1.1,1.2 numfmt.cpp,1.3,1.4 quant.cpp,1.5,1.6 quant.h,1.4,1.5 rbnf.cpp,1.5,1.6 rbt.cpp,1.4,1.5 rbt.h,1.1,1.2 rbt_data.cpp,1.4,1.5 rbt_data.h,1.4,1.5 rbt_pars.cpp,1.5,1.6 regexcmp.cpp,1.1,1.2 regexcst.h,1.1,1.2 regexcst.txt,1.1,1.2 regeximp.h,1.1,1.2 rematch.cpp,1.1,1.2 remtrans.cpp,1.4,1.5 remtrans.h,1.3,1.4 repattrn.cpp,1.1,1.2 simpletz.cpp,1.3,1.4 smpdtfmt.cpp,1.3,1.4 sortkey.cpp,1.3,1.4 strmatch.cpp,1.4,1.5 strmatch.h,1.4,1.5 strrepl.cpp,1.1,1.2 strrepl.h,1.1,1.2 stsearch.cpp,1.4,1.5 tblcoll.cpp,1.3,1.4 timezone.cpp,1.3,1.4 titletrn.cpp,1.4,1.5 titletrn.h,1.3,1.4 tolowtrn.cpp,1.4,1.5 tolowtrn.h,1.3,1.4 toupptrn.cpp,1.4,1.5 toupptrn.h,1.3,1.4 translit.cpp,1.5,1.6 transreg.cpp,1.5,1.6 tridpars.cpp,1.1,1.2 ucal.cpp,1.4,1.5 ucol.cpp,1.5,1.6 ucol_bld.cpp,1.5,1.6 ucol_cnt.cpp,1.5,1.6 ucol_elm.cpp,1.5,1.6 ucol_elm.h,1.5,1.6 ucol_imp.h,1.5,1.6 ucol_tok.cpp,1.5,1.6 ucol_tok.h,1.4,1.5 ucol_wgt.c,1.4,1.5

sword@www.crosswire.org sword@www.crosswire.org
Tue, 6 Apr 2004 03:11:38 -0700


Update of /cvs/core/icu-sword/source/i18n
In directory www:/tmp/cvs-serv8911/source/i18n

Modified Files:
	Makefile.in anytrans.cpp anytrans.h buddhcal.cpp buddhcal.h 
	calendar.cpp choicfmt.cpp coleitr.cpp coll.cpp cpdtrans.cpp 
	cpdtrans.h datefmt.cpp dcfmtsym.cpp decimfmt.cpp dtfmtsym.cpp 
	esctrn.cpp esctrn.h fmtable.cpp format.cpp funcrepl.cpp 
	funcrepl.h gregocal.cpp hextouni.cpp hextouni.h i18n.dsp 
	i18n.rc i18n.vcproj japancal.cpp japancal.h msgfmt.cpp 
	name2uni.cpp name2uni.h nfrs.cpp nfrule.cpp nfsubs.cpp 
	nortrans.cpp nortrans.h nultrans.cpp nultrans.h numfmt.cpp 
	quant.cpp quant.h rbnf.cpp rbt.cpp rbt.h rbt_data.cpp 
	rbt_data.h rbt_pars.cpp regexcmp.cpp regexcst.h regexcst.txt 
	regeximp.h rematch.cpp remtrans.cpp remtrans.h repattrn.cpp 
	simpletz.cpp smpdtfmt.cpp sortkey.cpp strmatch.cpp strmatch.h 
	strrepl.cpp strrepl.h stsearch.cpp tblcoll.cpp timezone.cpp 
	titletrn.cpp titletrn.h tolowtrn.cpp tolowtrn.h toupptrn.cpp 
	toupptrn.h translit.cpp transreg.cpp tridpars.cpp ucal.cpp 
	ucol.cpp ucol_bld.cpp ucol_cnt.cpp ucol_elm.cpp ucol_elm.h 
	ucol_imp.h ucol_tok.cpp ucol_tok.h ucol_wgt.c ucoleitr.cpp 
	ucurr.cpp udat.cpp umsg.cpp unesctrn.cpp unesctrn.h 
	uni2name.cpp uni2name.h unifltlg.cpp unitohex.cpp unitohex.h 
	unum.cpp usearch.cpp utrans.cpp 
Added Files:
	astro.cpp astro.h chnsecal.cpp chnsecal.h digitlst.cpp 
	digitlst.h gregoimp.cpp gregoimp.h hebrwcal.cpp hebrwcal.h 
	i18n.vcproj.old islamcal.cpp islamcal.h olsontz.cpp olsontz.h 
	ucurrimp.h ulocdata.c 
Removed Files:
	tzdat.h 
Log Message:
ICU 2.8 sync

--- NEW FILE: astro.cpp ---
/************************************************************************
 * Copyright (C) 1996-2003, International Business Machines Corporation *
 * and others. All Rights Reserved.                                     *
 ************************************************************************
 *  2003-nov-07   srl       Port from Java
 */

#include "astro.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/calendar.h"
#include "math.h"
#include <float.h>
#include "unicode/putil.h"
#include "uhash.h"
#include "umutex.h"
#include "ucln_in.h"
#include <stdio.h>  // for toString()
[...1504 lines suppressed...]
CalendarCache::CalendarCache(int32_t size, UErrorCode &status) {
  fTable = uhash_openSize(uhash_hashLong, uhash_compareLong, size, &status);
  U_DEBUG_ASTRO_MSG(("%p: Opening.\n", fTable));
}

CalendarCache::~CalendarCache() {
  if(fTable != NULL) {
    U_DEBUG_ASTRO_MSG(("%p: Closing.\n", fTable));
    uhash_close(fTable);
  }
}

U_NAMESPACE_END

U_CFUNC UBool calendar_astro_cleanup(void) {
  umtx_destroy(&ccLock);
  return TRUE;
}

#endif //  !UCONFIG_NO_FORMATTING

--- NEW FILE: astro.h ---
/************************************************************************
 * Copyright (C) 1996-2003, International Business Machines Corporation *
 * and others. All Rights Reserved.                                     *
 ************************************************************************
 *  2003-nov-07   srl       Port from Java
 */

#ifndef ASTRO_H
#define ASTRO_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "gregoimp.h"  // for Math
#include "unicode/unistr.h"

U_NAMESPACE_BEGIN

/**
 * <code>CalendarAstronomer</code> is a class that can perform the calculations to
 * determine the positions of the sun and moon, the time of sunrise and
 * sunset, and other astronomy-related data.  The calculations it performs
 * are in some cases quite complicated, and this utility class saves you
 * the trouble of worrying about them.
 * <p>
 * The measurement of time is a very important part of astronomy.  Because
 * astronomical bodies are constantly in motion, observations are only valid
 * at a given moment in time.  Accordingly, each <code>CalendarAstronomer</code>
 * object has a <code>time</code> property that determines the date
 * and time for which its calculations are performed.  You can set and
 * retrieve this property with {@link #setDate setDate}, {@link #getDate getDate}
 * and related methods.
 * <p>
 * Almost all of the calculations performed by this class, or by any
 * astronomer, are approximations to various degrees of accuracy.  The
 * calculations in this class are mostly modelled after those described
 * in the book
 * <a href="http://www.amazon.com/exec/obidos/ISBN=0521356997" target="_top">
 * Practical Astronomy With Your Calculator</a>, by Peter J.
 * Duffett-Smith, Cambridge University Press, 1990.  This is an excellent
 * book, and if you want a greater understanding of how these calculations
 * are performed it a very good, readable starting point.
 * <p>
 * <strong>WARNING:</strong> This class is very early in its development, and
 * it is highly likely that its API will change to some degree in the future.
 * At the moment, it basically does just enough to support {@link IslamicCalendar}
 * and {@link ChineseCalendar}.
 *
 * @author Laura Werner
 * @author Alan Liu
 * @internal
 */
class U_I18N_API CalendarAstronomer : public UMemory {
public:
  // some classes

public:
  /**
   * Represents the position of an object in the sky relative to the ecliptic,
   * the plane of the earth's orbit around the Sun.
   * This is a spherical coordinate system in which the latitude
   * specifies the position north or south of the plane of the ecliptic.
   * The longitude specifies the position along the ecliptic plane
   * relative to the "First Point of Aries", which is the Sun's position in the sky
   * at the Vernal Equinox.
   * <p>
   * Note that Ecliptic objects are immutable and cannot be modified
   * once they are constructed.  This allows them to be passed and returned by
   * value without worrying about whether other code will modify them.
   *
   * @see CalendarAstronomer.Equatorial
   * @see CalendarAstronomer.Horizon
   * @internal
   */
  class U_I18N_API Ecliptic : public UMemory {
  public:
    /**
     * Constructs an Ecliptic coordinate object.
     * <p>
     * @param lat The ecliptic latitude, measured in radians.
     * @param lon The ecliptic longitude, measured in radians.
     * @internal
     */
    Ecliptic(double lat = 0, double lon = 0) {
      latitude = lat;
      longitude = lon;
    }

    /**
     * Setter for Ecliptic Coordinate object
     * @param lat The ecliptic latitude, measured in radians.
     * @param lon The ecliptic longitude, measured in radians.
     * @internal
     */
    void set(double lat, double lon) {
      latitude = lat;
      longitude = lon;
    }

    /**
     * Return a string representation of this object
     * @internal
     */
    UnicodeString toString() const;

    /**
     * The ecliptic latitude, in radians.  This specifies an object's
     * position north or south of the plane of the ecliptic,
     * with positive angles representing north.
     * @internal
     */
    double latitude;

    /**
     * The ecliptic longitude, in radians.
     * This specifies an object's position along the ecliptic plane
     * relative to the "First Point of Aries", which is the Sun's position
     * in the sky at the Vernal Equinox,
     * with positive angles representing east.
     * <p>
     * A bit of trivia: the first point of Aries is currently in the
     * constellation Pisces, due to the precession of the earth's axis.
     * @internal
     */
    double longitude;
  };

  /**
   * Represents the position of an
   * object in the sky relative to the plane of the earth's equator.
   * The <i>Right Ascension</i> specifies the position east or west
   * along the equator, relative to the sun's position at the vernal
   * equinox.  The <i>Declination</i> is the position north or south
   * of the equatorial plane.
   * <p>
   * Note that Equatorial objects are immutable and cannot be modified
   * once they are constructed.  This allows them to be passed and returned by
   * value without worrying about whether other code will modify them.
   *
   * @see CalendarAstronomer.Ecliptic
   * @see CalendarAstronomer.Horizon
   * @internal
   */
  class U_I18N_API Equatorial : public UMemory {
  public:
    /**
     * Constructs an Equatorial coordinate object.
     * <p>
     * @param asc The right ascension, measured in radians.
     * @param dec The declination, measured in radians.
     * @internal
     */
    Equatorial(double asc = 0, double dec = 0)
      : ascension(asc), declination(dec) { }

    /**
     * Setter
     * @param asc The right ascension, measured in radians.
     * @param dec The declination, measured in radians.
     * @internal
     */
    void set(double asc, double dec) {
      ascension = asc;
      declination = dec;
    }

    /**
     * Return a string representation of this object, with the
     * angles measured in degrees.
     * @internal
     */
    UnicodeString toString() const;

    /**
     * Return a string representation of this object with the right ascension
     * measured in hours, minutes, and seconds.
     * @internal
     */
    //String toHmsString() {
    //return radToHms(ascension) + "," + radToDms(declination);
    //}

    /**
     * The right ascension, in radians.
     * This is the position east or west along the equator
     * relative to the sun's position at the vernal equinox,
     * with positive angles representing East.
     * @internal
     */
    double ascension;

    /**
     * The declination, in radians.
     * This is the position north or south of the equatorial plane,
     * with positive angles representing north.
     * @internal
     */
    double declination;
  };

  /**
   * Represents the position of an  object in the sky relative to
   * the local horizon.
   * The <i>Altitude</i> represents the object's elevation above the horizon,
   * with objects below the horizon having a negative altitude.
   * The <i>Azimuth</i> is the geographic direction of the object from the
   * observer's position, with 0 representing north.  The azimuth increases
   * clockwise from north.
   * <p>
   * Note that Horizon objects are immutable and cannot be modified
   * once they are constructed.  This allows them to be passed and returned by
   * value without worrying about whether other code will modify them.
   *
   * @see CalendarAstronomer.Ecliptic
   * @see CalendarAstronomer.Equatorial
   * @internal
   */
  class U_I18N_API Horizon : public UMemory {
  public:
    /**
     * Constructs a Horizon coordinate object.
     * <p>
     * @param alt  The altitude, measured in radians above the horizon.
     * @param azim The azimuth, measured in radians clockwise from north.
     * @internal
     */
    Horizon(double alt=0, double azim=0)
      : altitude(alt), azimuth(azim) { }

    /**
     * Setter for Ecliptic Coordinate object
     * @param alt  The altitude, measured in radians above the horizon.
     * @param azim The azimuth, measured in radians clockwise from north.
     * @internal
     */
    void set(double alt, double azim) {
      altitude = alt;
      azimuth = azim;
    }

    /**
     * Return a string representation of this object, with the
     * angles measured in degrees.
     * @internal
     */
    UnicodeString toString() const;

    /**
     * The object's altitude above the horizon, in radians.
     * @internal
     */
    double altitude;

    /**
     * The object's direction, in radians clockwise from north.
     * @internal
     */
    double azimuth;
  };

public:
  //-------------------------------------------------------------------------
  // Assorted private data used for conversions
  //-------------------------------------------------------------------------

  // My own copies of these so compilers are more likely to optimize them away
  static const double PI;

  /**
   * The average number of solar days from one new moon to the next.  This is the time
   * it takes for the moon to return the same ecliptic longitude as the sun.
   * It is longer than the sidereal month because the sun's longitude increases
   * during the year due to the revolution of the earth around the sun.
   * Approximately 29.53.
   *
   * @see #SIDEREAL_MONTH
   * @internal
   * @deprecated ICU 2.4. This class may be removed or modified.
   */
  static const double SYNODIC_MONTH;

  //-------------------------------------------------------------------------
  // Constructors
  //-------------------------------------------------------------------------

  /**
   * Construct a new <code>CalendarAstronomer</code> object that is initialized to
   * the current date and time.
   * @internal
   */
  CalendarAstronomer();

  /**
   * Construct a new <code>CalendarAstronomer</code> object that is initialized to
   * the specified date and time.
   * @internal
   */
  CalendarAstronomer(UDate d);

  /**
   * Construct a new <code>CalendarAstronomer</code> object with the given
   * latitude and longitude.  The object's time is set to the current
   * date and time.
   * <p>
   * @param longitude The desired longitude, in <em>degrees</em> east of
   *                  the Greenwich meridian.
   *
   * @param latitude  The desired latitude, in <em>degrees</em>.  Positive
   *                  values signify North, negative South.
   *
   * @see java.util.Date#getTime()
   * @internal
   */
  CalendarAstronomer(double longitude, double latitude);

  /**
   * Destructor
   * @internal
   */
  ~CalendarAstronomer();

  //-------------------------------------------------------------------------
  // Time and date getters and setters
  //-------------------------------------------------------------------------

  /**
   * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
   * astronomical calculations are performed based on this time setting.
   *
   * @param aTime the date and time, expressed as the number of milliseconds since
   *              1/1/1970 0:00 GMT (Gregorian).
   *
   * @see #setDate
   * @see #getTime
   * @internal
   */
  void setTime(UDate aTime);


  /**
   * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
   * astronomical calculations are performed based on this time setting.
   *
   * @param aTime the date and time, expressed as the number of milliseconds since
   *              1/1/1970 0:00 GMT (Gregorian).
   *
   * @see #getTime
   * @internal
   */
  void setDate(UDate aDate) { setTime(aDate); }

  /**
   * Set the current date and time of this <code>CalendarAstronomer</code> object.  All
   * astronomical calculations are performed based on this time setting.
   *
   * @param jdn   the desired time, expressed as a "julian day number",
   *              which is the number of elapsed days since
   *              1/1/4713 BC (Julian), 12:00 GMT.  Note that julian day
   *              numbers start at <em>noon</em>.  To get the jdn for
   *              the corresponding midnight, subtract 0.5.
   *
   * @see #getJulianDay
   * @see #JULIAN_EPOCH_MS
   * @internal
   */
  void setJulianDay(double jdn);

  /**
   * Get the current time of this <code>CalendarAstronomer</code> object,
   * represented as the number of milliseconds since
   * 1/1/1970 AD 0:00 GMT (Gregorian).
   *
   * @see #setTime
   * @see #getDate
   * @internal
   */
  UDate getTime();

  /**
   * Get the current time of this <code>CalendarAstronomer</code> object,
   * expressed as a "julian day number", which is the number of elapsed
   * days since 1/1/4713 BC (Julian), 12:00 GMT.
   *
   * @see #setJulianDay
   * @see #JULIAN_EPOCH_MS
   * @internal
   */
  double getJulianDay();

  /**
   * Return this object's time expressed in julian centuries:
   * the number of centuries after 1/1/1900 AD, 12:00 GMT
   *
   * @see #getJulianDay
   * @internal
   */
  double getJulianCentury();

  /**
   * Returns the current Greenwich sidereal time, measured in hours
   * @internal
   */
  double getGreenwichSidereal();

private:
  double getSiderealOffset();
public:
  /**
   * Returns the current local sidereal time, measured in hours
   * @internal
   */
  double getLocalSidereal();

  /**
   * Converts local sidereal time to Universal Time.
   *
   * @param lst   The Local Sidereal Time, in hours since sidereal midnight
   *              on this object's current date.
   *
   * @return      The corresponding Universal Time, in milliseconds since
   *              1 Jan 1970, GMT.
   */
  //private:
  double lstToUT(double lst);

  /**
   *
   * Convert from ecliptic to equatorial coordinates.
   *
   * @param ecliptic     The ecliptic
   * @param result       Fillin result
   * @return reference to result
   */
  Equatorial& eclipticToEquatorial(Equatorial& result, const Ecliptic& ecliptic);

  /**
   * Convert from ecliptic to equatorial coordinates.
   *
   * @param eclipLong     The ecliptic longitude
   * @param eclipLat      The ecliptic latitude
   *
   * @return              The corresponding point in equatorial coordinates.
   * @internal
   */
  Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong, double eclipLat);

  /**
   * Convert from ecliptic longitude to equatorial coordinates.
   *
   * @param eclipLong     The ecliptic longitude
   *
   * @return              The corresponding point in equatorial coordinates.
   * @internal
   */
  Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong) ;

  /**
   * @internal
   */
  Horizon& eclipticToHorizon(Horizon& result, double eclipLong) ;

  //-------------------------------------------------------------------------
  // The Sun
  //-------------------------------------------------------------------------

  /**
   * The longitude of the sun at the time specified by this object.
   * The longitude is measured in radians along the ecliptic
   * from the "first point of Aries," the point at which the ecliptic
   * crosses the earth's equatorial plane at the vernal equinox.
   * <p>
   * Currently, this method uses an approximation of the two-body Kepler's
   * equation for the earth and the sun.  It does not take into account the
   * perturbations caused by the other planets, the moon, etc.
   * @internal
   */
  double getSunLongitude();

  /**
   * TODO Make this public when the entire class is package-private.
   */
  /*public*/ void getSunLongitude(double julianDay, double &longitude, double &meanAnomaly);

  /**
   * The position of the sun at this object's current date and time,
   * in equatorial coordinates.
   * @param result fillin for the result
   * @internal
   */
  Equatorial& getSunPosition(Equatorial& result);

public:
  /**
   * Constant representing the vernal equinox.
   * For use with {@link #getSunTime getSunTime}.
   * Note: In this case, "vernal" refers to the northern hemisphere's seasons.
   * @internal
   */
  static double VERNAL_EQUINOX();

  /**
   * Constant representing the summer solstice.
   * For use with {@link #getSunTime getSunTime}.
   * Note: In this case, "summer" refers to the northern hemisphere's seasons.
   * @internal
   */
  static double SUMMER_SOLSTICE();

  /**
   * Constant representing the autumnal equinox.
   * For use with {@link #getSunTime getSunTime}.
   * Note: In this case, "autumn" refers to the northern hemisphere's seasons.
   * @internal
   */
  static double AUTUMN_EQUINOX();

  /**
   * Constant representing the winter solstice.
   * For use with {@link #getSunTime getSunTime}.
   * Note: In this case, "winter" refers to the northern hemisphere's seasons.
   * @internal
   */
  static double WINTER_SOLSTICE();

  /**
   * Find the next time at which the sun's ecliptic longitude will have
   * the desired value.
   * @internal
   */
  UDate getSunTime(double desired, UBool next);

  /**
   * Returns the time (GMT) of sunrise or sunset on the local date to which
   * this calendar is currently set.
   *
   * NOTE: This method only works well if this object is set to a
   * time near local noon.  Because of variations between the local
   * official time zone and the geographic longitude, the
   * computation can flop over into an adjacent day if this object
   * is set to a time near local midnight.
   *
   * @internal
   */
  UDate getSunRiseSet(UBool rise);

  //-------------------------------------------------------------------------
  // The Moon
  //-------------------------------------------------------------------------

  /**
   * The position of the moon at the time set on this
   * object, in equatorial coordinates.
   * @internal
   * @return const reference to internal field of calendar astronomer. Do not use outside of the lifetime of this astronomer.
   */
  const Equatorial& getMoonPosition();

  /**
   * The "age" of the moon at the time specified in this object.
   * This is really the angle between the
   * current ecliptic longitudes of the sun and the moon,
   * measured in radians.
   *
   * @see #getMoonPhase
   * @internal
   */
  double getMoonAge();

  /**
   * Calculate the phase of the moon at the time set in this object.
   * The returned phase is a <code>double</code> in the range
   * <code>0 <= phase < 1</code>, interpreted as follows:
   * <ul>
   * <li>0.00: New moon
   * <li>0.25: First quarter
   * <li>0.50: Full moon
   * <li>0.75: Last quarter
   * </ul>
   *
   * @see #getMoonAge
   * @internal
   */
  double getMoonPhase();

  class U_I18N_API MoonAge : public UMemory {
  public:
    MoonAge(double l)
      :  value(l) { }
    void set(double l) { value = l; }
    double value;
  };

  /**
   * Constant representing a new moon.
   * For use with {@link #getMoonTime getMoonTime}
   * @internal
   */
  static const MoonAge NEW_MOON();

  /**
   * Constant representing the moon's first quarter.
   * For use with {@link #getMoonTime getMoonTime}
   * @internal
   */
  static const MoonAge FIRST_QUARTER();

  /**
   * Constant representing a full moon.
   * For use with {@link #getMoonTime getMoonTime}
   * @internal
   */
  static const MoonAge FULL_MOON();

  /**
   * Constant representing the moon's last quarter.
   * For use with {@link #getMoonTime getMoonTime}
   * @internal
   */
  static const MoonAge LAST_QUARTER();

  /**
   * Find the next or previous time at which the Moon's ecliptic
   * longitude will have the desired value.
   * <p>
   * @param desired   The desired longitude.
   * @param next      <tt>true</tt> if the next occurrance of the phase
   *                  is desired, <tt>false</tt> for the previous occurrance.
   * @internal
   */
  UDate getMoonTime(double desired, UBool next);
  UDate getMoonTime(const MoonAge& desired, UBool next);

  /**
   * Returns the time (GMT) of sunrise or sunset on the local date to which
   * this calendar is currently set.
   * @internal
   */
  UDate getMoonRiseSet(UBool rise);

  //-------------------------------------------------------------------------
  // Interpolation methods for finding the time at which a given event occurs
  //-------------------------------------------------------------------------

  // private
  class U_I18N_API AngleFunc : public UMemory {
  public:
    virtual double eval(CalendarAstronomer&) = 0;
  };
  friend class AngleFunc;

  UDate timeOfAngle(AngleFunc& func, double desired,
                    double periodDays, double epsilon, UBool next);

  class U_I18N_API CoordFunc : public UMemory {
  public:
    virtual void eval(Equatorial& result, CalendarAstronomer&) = 0;
  };
  friend class CoordFunc;

  double riseOrSet(CoordFunc& func, UBool rise,
                   double diameter, double refraction,
                   double epsilon);

  //-------------------------------------------------------------------------
  // Other utility methods
  //-------------------------------------------------------------------------
private:
  /***
   * Given 'value', add or subtract 'range' until 0 <= 'value' < range.
   * The modulus operator.
   */
  inline static double normalize(double value, double range)  {
    return value - range * Math::floorDivide(value, range);
  }

  /**
   * Normalize an angle so that it's in the range 0 - 2pi.
   * For positive angles this is just (angle % 2pi), but the Java
   * mod operator doesn't work that way for negative numbers....
   */
  inline static double norm2PI(double angle)  {
    return normalize(angle, CalendarAstronomer::PI * 2.0);
  }

  /**
   * Normalize an angle into the range -PI - PI
   */
  inline static  double normPI(double angle)  {
    return normalize(angle + PI, CalendarAstronomer::PI * 2.0) - PI;
  }

  /**
   * Find the "true anomaly" (longitude) of an object from
   * its mean anomaly and the eccentricity of its orbit.  This uses
   * an iterative solution to Kepler's equation.
   *
   * @param meanAnomaly   The object's longitude calculated as if it were in
   *                      a regular, circular orbit, measured in radians
   *                      from the point of perigee.
   *
   * @param eccentricity  The eccentricity of the orbit
   *
   * @return The true anomaly (longitude) measured in radians
   */
  double trueAnomaly(double meanAnomaly, double eccentricity);

  /**
   * Return the obliquity of the ecliptic (the angle between the ecliptic
   * and the earth's equator) at the current time.  This varies due to
   * the precession of the earth's axis.
   *
   * @return  the obliquity of the ecliptic relative to the equator,
   *          measured in radians.
   */
  double eclipticObliquity();

  //-------------------------------------------------------------------------
  // Private data
  //-------------------------------------------------------------------------
private:
  /**
   * Current time in milliseconds since 1/1/1970 AD
   * @see java.util.Date#getTime
   */
  UDate fTime;

  /* These aren't used yet, but they'll be needed for sunset calculations
   * and equatorial to horizon coordinate conversions
   */
  double fLongitude;
  double fLatitude;
  double fGmtOffset;

  //
  // The following fields are used to cache calculated results for improved
  // performance.  These values all depend on the current time setting
  // of this object, so the clearCache method is provided.
  //

  double    julianDay       ;
  double    julianCentury   ;
  double    sunLongitude    ;
  double    meanAnomalySun  ;
  double    moonLongitude   ;
  double    moonEclipLong   ;
  double    meanAnomalyMoon ;
  double    eclipObliquity  ;
  double    siderealT0      ;
  double    siderealTime    ;

  void clearCache();

  Equatorial  moonPosition;
  UBool       moonPositionSet;

  /**
   * @internal
   */
  UDate local(UDate localMillis);
};

U_NAMESPACE_END

struct UHashtable;

U_NAMESPACE_BEGIN

/**
 * Cache of month -> julian day
 * @internal
 */
class U_I18N_API CalendarCache : public UMemory {
public:
  static int32_t get(CalendarCache** cache, int32_t key, UErrorCode &status);
  static void put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status);
  virtual ~CalendarCache();
private:
  CalendarCache(int32_t size, UErrorCode& status);
  static void createCache(CalendarCache** cache, UErrorCode& status);
  /**
   * not implemented
   */
  CalendarCache();
  UHashtable *fTable;
};

U_NAMESPACE_END

#endif
#endif

--- NEW FILE: chnsecal.cpp ---
/*
 ******************************************************************************
 * Copyright (C) 2003-2004, International Business Machines Corporation and   *
 * others. All Rights Reserved.                                               *
 ******************************************************************************
 *
 *
 ******************************************************************************
 */
#include "chnsecal.h"

// Placeholder for now until the implementation can be finished.


--- NEW FILE: chnsecal.h ---
/*
 ******************************************************************************
 * Copyright (C) 1996-2003, International Business Machines Corporation and   *
 * others. All Rights Reserved.                                               *
 ******************************************************************************
 *
 *
 **************************************************************************
 */

// placeholder

--- NEW FILE: digitlst.cpp ---
/*
**********************************************************************
*   Copyright (C) 1997-2003, International Business Machines
*   Corporation and others.  All Rights Reserved.
**********************************************************************
*
* File DIGITLST.CPP
*
* Modification History:
*
*   Date        Name        Description
*   03/21/97    clhuang     Converted from java.
*   03/21/97    clhuang     Implemented with new APIs.
*   03/27/97    helena      Updated to pass the simple test after code review.
*   03/31/97    aliu        Moved isLONG_MIN to here, and fixed it.
*   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
*                           Reworked representation by replacing fDecimalAt
*                           with fExponent.
*   04/16/97    aliu        Rewrote set() and getDouble() to use sprintf/atof
*                           to do digit conversion.
*   09/09/97    aliu        Modified for exponential notation support.
*   08/02/98    stephen     Added nearest/even rounding
*                            Fixed bug in fitsIntoLong
******************************************************************************
*/

#include "unicode/putil.h"
#include "digitlst.h"
#include "cstring.h"
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>

// ***************************************************************************
// class DigitList
// This class handles the transcoding between numeric values and strings of
//  characters.  Only handles as non-negative numbers.  
// ***************************************************************************

/**
 * This is the zero digit.  Array elements fDigits[i] have values from
 * kZero to kZero + 9.  Typically, this is '0'.
 */
#define kZero '0'

static char gDecimal = 0;

/* Only for 32 bit numbers. Ignore the negative sign. */
static const char LONG_MIN_REP[] = "2147483648";
static const char I64_MIN_REP[] = "9223372036854775808";

static const int64_t I64_MIN_VALUE = U_INT64_MIN;

enum {
    LONG_MIN_REP_LENGTH = sizeof(LONG_MIN_REP) - 1, //Ignore the NULL at the end
    I64_MIN_REP_LENGTH = sizeof(I64_MIN_REP) - 1 //Ignore the NULL at the end
};

U_NAMESPACE_BEGIN


// -------------------------------------
// default constructor

DigitList::DigitList()
{
    clear();
}

// -------------------------------------

DigitList::~DigitList()
{
}

// -------------------------------------
// copy constructor

DigitList::DigitList(const DigitList &other)
{
    fDigits = fDecimalDigits + 1;   // skip the decimal
    *this = other;
}

// -------------------------------------
// assignment operator

DigitList&
DigitList::operator=(const DigitList& other)
{
    if (this != &other)
    {
        fDecimalAt = other.fDecimalAt;
        fCount = other.fCount;
        fIsPositive = other.fIsPositive;
        uprv_strncpy(fDigits, other.fDigits, fCount);
    }
    return *this;
}

// -------------------------------------

UBool
DigitList::operator==(const DigitList& that) const
{
    return ((this == &that) ||
            (fDecimalAt == that.fDecimalAt &&
             fCount == that.fCount &&
             fIsPositive == that.fIsPositive &&
             uprv_strncmp(fDigits, that.fDigits, fCount) == 0));
}

// -------------------------------------
// Resets the digit list; sets all the digits to zero.

void
DigitList::clear()
{
    fDigits = fDecimalDigits + 1;   // skip the decimal
    fDecimalAt = 0;
    fCount = 0;
    fIsPositive = TRUE;

    // Don't bother initializing fDigits because fCount is 0.
}



// -------------------------------------

/**
 * Formats a number into a base 10 string representation, and NULL terminates it.
 * @param number The number to format
 * @param outputStr The string to output to
 * @param outputLen The maximum number of characters to put into outputStr
 *                  (including NULL).
 * @return the number of digits written, not including the sign.
 */
static int32_t
formatBase10(int64_t number, char *outputStr, int32_t outputLen) 
{
    char buffer[MAX_DIGITS + 1];
    int32_t bufferLen;
    int32_t result;

    if (outputLen > MAX_DIGITS) {
        outputLen = MAX_DIGITS;     // Ignore NULL
    }
    else if (outputLen < 3) {
        return 0;                   // Not enough room
    }

    bufferLen = outputLen;

    if (number < 0) {   // Negative numbers are slightly larger than a postive
        buffer[bufferLen--] = (char)(-(number % 10) + kZero);
        number /= -10;
        *(outputStr++) = '-';
    }
    else {
        *(outputStr++) = '+';    // allow +0
    }
    while (bufferLen >= 0 && number) {      // Output the number
        buffer[bufferLen--] = (char)(number % 10 + kZero);
        number /= 10;
    }

    result = outputLen - bufferLen++;

    while (bufferLen <= outputLen) {     // Copy the number to output
        *(outputStr++) = buffer[bufferLen++];
    }
    *outputStr = 0;   // NULL terminate.
    return result;
}

/**
 * Currently, getDouble() depends on atof() to do its conversion.
 *
 * WARNING!!
 * This is an extremely costly function. ~1/2 of the conversion time
 * can be linked to this function.
 */
double
DigitList::getDouble()
{
    double value;

    if (fCount == 0) {
        value = 0.0;
    }
    else {
        if (!gDecimal) {
            char rep[MAX_DIGITS];
            // For machines that decide to change the decimal on you,
            // and try to be too smart with localization.
            // This normally should be just a '.'.
            sprintf(rep, "%+1.1f", 1.0);
            gDecimal = rep[2];
        }

        *fDecimalDigits = gDecimal;
        *(fDigits+fCount) = 'e';    // add an e after the digits.
        formatBase10(fDecimalAt,
                     fDigits + fCount + 1,  // skip the 'e'
                     MAX_DEC_DIGITS - fCount - 3);  // skip the 'e' and '.'
        value = atof(fDecimalDigits);
    }

    return fIsPositive ? value : -value;
}

// -------------------------------------

/**
 * Make sure that fitsIntoLong() is called before calling this function.
 */
int32_t DigitList::getLong()
{
    if (fCount == fDecimalAt) {
        int32_t value;

        fDigits[fCount] = 0;    // NULL terminate

        // This conversion is bad on 64-bit platforms when we want to
        // be able to return a 64-bit number [grhoten]
        *fDecimalDigits = fIsPositive ? '+' : '-';
        value = (int32_t)atol(fDecimalDigits);
        return value;
    }
    else {
        // This is 100% accurate in c++ because if we are representing
        // an integral value, we suffer nothing in the conversion to
        // double.  If we are to support 64-bit longs later, getLong()
        // must be rewritten. [LIU]
        return (int32_t)getDouble();
    }
}


/**
 * Make sure that fitsIntoInt64() is called before calling this function.
 */
int64_t DigitList::getInt64()
{
    if (fCount == fDecimalAt) {
        uint64_t value;

        fDigits[fCount] = 0;    // NULL terminate

        // This conversion is bad on 64-bit platforms when we want to
        // be able to return a 64-bit number [grhoten]
        *fDecimalDigits = fIsPositive ? '+' : '-';

		if (fCount < LONG_MIN_REP_LENGTH) {
			return (int64_t)atol(fDecimalDigits);
		}

		// too big for atol, hand-roll atoi64
		value = 0;
		for (int i = 0; i < fCount; ++i) {
			int v = fDigits[i] - kZero;
			value = value * (uint64_t)10 + (uint64_t)v;
		}
		if (!fIsPositive) {
			value = ~value;
			value += 1;
		}
		int64_t svalue = (int64_t)value;
        return svalue;
    }
    else {
		// todo: figure out best approach

        // This is 100% accurate in c++ because if we are representing
        // an integral value, we suffer nothing in the conversion to
        // double.  If we are to support 64-bit longs later, getLong()
        // must be rewritten. [LIU]
        return (int64_t)getDouble();
    }
}

/**
 * Return true if the number represented by this object can fit into
 * a long.
 */
UBool
DigitList::fitsIntoLong(UBool ignoreNegativeZero)
{
    // Figure out if the result will fit in a long.  We have to
    // first look for nonzero digits after the decimal point;
    // then check the size.

    // Trim trailing zeros after the decimal point. This does not change
    // the represented value.
    while (fCount > fDecimalAt && fCount > 0 && fDigits[fCount - 1] == kZero)
        --fCount;

    if (fCount == 0) {
        // Positive zero fits into a long, but negative zero can only
        // be represented as a double. - bug 4162852
        return fIsPositive || ignoreNegativeZero;
    }

//    initializeLONG_MIN_REP();

    // If the digit list represents a double or this number is too
    // big for a long.
    if (fDecimalAt < fCount || fDecimalAt > LONG_MIN_REP_LENGTH)
        return FALSE;

    // If number is small enough to fit in a long
    if (fDecimalAt < LONG_MIN_REP_LENGTH)
        return TRUE;

    // At this point we have fDecimalAt == fCount, and fCount == LONG_MIN_REP_LENGTH.
    // The number will overflow if it is larger than LONG_MAX
    // or smaller than LONG_MIN.
    for (int32_t i=0; i<fCount; ++i)
    {
        char dig = fDigits[i],
             max = LONG_MIN_REP[i];
        if (dig > max)
            return FALSE;
        if (dig < max)
            return TRUE;
    }

    // At this point the first count digits match.  If fDecimalAt is less
    // than count, then the remaining digits are zero, and we return true.
    if (fCount < fDecimalAt)
        return TRUE;

    // Now we have a representation of Long.MIN_VALUE, without the leading
    // negative sign.  If this represents a positive value, then it does
    // not fit; otherwise it fits.
    return !fIsPositive;
}

/**
 * Return true if the number represented by this object can fit into
 * a long.
 */
UBool
DigitList::fitsIntoInt64(UBool ignoreNegativeZero)
{
    // Figure out if the result will fit in a long.  We have to
    // first look for nonzero digits after the decimal point;
    // then check the size.

    // Trim trailing zeros after the decimal point. This does not change
    // the represented value.
    while (fCount > fDecimalAt && fCount > 0 && fDigits[fCount - 1] == kZero)
        --fCount;

    if (fCount == 0) {
        // Positive zero fits into a long, but negative zero can only
        // be represented as a double. - bug 4162852
        return fIsPositive || ignoreNegativeZero;
    }

//    initializeLONG_MIN_REP();

    // If the digit list represents a double or this number is too
    // big for a long.
    if (fDecimalAt < fCount || fDecimalAt > I64_MIN_REP_LENGTH)
        return FALSE;

    // If number is small enough to fit in an int64
    if (fDecimalAt < I64_MIN_REP_LENGTH)
        return TRUE;

    // At this point we have fDecimalAt == fCount, and fCount == INT64_MIN_REP_LENGTH.
    // The number will overflow if it is larger than U_INT64_MAX
    // or smaller than U_INT64_MIN.
    for (int32_t i=0; i<fCount; ++i)
    {
        char dig = fDigits[i],
             max = I64_MIN_REP[i];
        if (dig > max)
            return FALSE;
        if (dig < max)
            return TRUE;
    }

    // At this point the first count digits match.  If fDecimalAt is less
    // than count, then the remaining digits are zero, and we return true.
    if (fCount < fDecimalAt)
        return TRUE;

    // Now we have a representation of INT64_MIN_VALUE, without the leading
    // negative sign.  If this represents a positive value, then it does
    // not fit; otherwise it fits.
    return !fIsPositive;
}


// -------------------------------------

void
DigitList::set(int32_t source, int32_t maximumDigits)
{
	set((int64_t)source, maximumDigits);
}

// -------------------------------------
/**
 * @param maximumDigits The maximum digits to be generated.  If zero,
 * there is no maximum -- generate all digits.
 */
void
DigitList::set(int64_t source, int32_t maximumDigits)
{
    fCount = fDecimalAt = formatBase10(source, fDecimalDigits, MAX_DIGITS);

    fIsPositive = (*fDecimalDigits == '+');
    
    // Don't copy trailing zeros
    while (fCount > 1 && fDigits[fCount - 1] == kZero) 
        --fCount;
    
    if(maximumDigits > 0) 
        round(maximumDigits);
}

/**
 * Set the digit list to a representation of the given double value.
 * This method supports both fixed-point and exponential notation.
 * @param source Value to be converted; must not be Inf, -Inf, Nan,
 * or a value <= 0.
 * @param maximumDigits The most fractional or total digits which should
 * be converted.  If total digits, and the value is zero, then
 * there is no maximum -- generate all digits.
 * @param fixedPoint If true, then maximumDigits is the maximum
 * fractional digits to be converted.  If false, total digits.
 */
void
DigitList::set(double source, int32_t maximumDigits, UBool fixedPoint)
{
    // for now, simple implementation; later, do proper IEEE stuff
    char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough)
    char *digitPtr      = fDigits;
    char *repPtr        = rep + 2;  // +2 to skip the sign and decimal
    int32_t exponent    = 0;

    fIsPositive = !uprv_isNegative(source);    // Allow +0 and -0

    // Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/
    sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
    fDecimalAt  = 0;
    rep[2]      = rep[1];    // remove decimal

    while (*repPtr == kZero) {
        repPtr++;
        fDecimalAt--;   // account for leading zeros
    }

    while (*repPtr != 'e') {
        *(digitPtr++) = *(repPtr++);
    }
    fCount = MAX_DBL_DIGITS + fDecimalAt;

    // Parse an exponent of the form /[eE][+-][0-9]+/
    UBool negExp = (*(++repPtr) == '-');
    while (*(++repPtr) != 0) {
        exponent = 10*exponent + *repPtr - kZero;
    }
    if (negExp) {
        exponent = -exponent;
    }
    fDecimalAt += exponent + 1; // +1 for decimal removal

    // The negative of the exponent represents the number of leading
    // zeros between the decimal and the first non-zero digit, for
    // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2).  If this
    // is more than the maximum fraction digits, then we have an underflow
    // for the printed representation.
    if (fixedPoint && -fDecimalAt >= maximumDigits)
    {
        // If we round 0.0009 to 3 fractional digits, then we have to
        // create a new one digit in the least significant location.
        if (-fDecimalAt == maximumDigits && shouldRoundUp(0)) {
            fCount = 1;
            ++fDecimalAt;
            fDigits[0] = (char)'1';
        } else {
            // Handle an underflow to zero when we round something like
            // 0.0009 to 2 fractional digits.
            fCount = 0;
        }
        return;
    }


    // Eliminate digits beyond maximum digits to be displayed.
    // Round up if appropriate.  Do NOT round in the special
    // case where maximumDigits == 0 and fixedPoint is FALSE.
    if (fixedPoint || (0 < maximumDigits && maximumDigits < fCount)) {
        round(fixedPoint ? (maximumDigits + fDecimalAt) : maximumDigits);
    }
    else {
        // Eliminate trailing zeros.
        while (fCount > 1 && fDigits[fCount - 1] == kZero)
            --fCount;
    }
}

// -------------------------------------

/**
 * Round the representation to the given number of digits.
 * @param maximumDigits The maximum number of digits to be shown.
 * Upon return, count will be less than or equal to maximumDigits.
 */
void 
DigitList::round(int32_t maximumDigits)
{
    // Eliminate digits beyond maximum digits to be displayed.
    // Round up if appropriate.
    if (maximumDigits >= 0 && maximumDigits < fCount)
    {
        if (shouldRoundUp(maximumDigits)) {
            // Rounding up involved incrementing digits from LSD to MSD.
            // In most cases this is simple, but in a worst case situation
            // (9999..99) we have to adjust the decimalAt value.
            while (--maximumDigits >= 0 && ++fDigits[maximumDigits] > '9')
                ;

            if (maximumDigits < 0)
            {
                // We have all 9's, so we increment to a single digit
                // of one and adjust the exponent.
                fDigits[0] = (char) '1';
                ++fDecimalAt;
                maximumDigits = 1; // Adjust the count
            }
            else
            {
                ++maximumDigits; // Increment for use as count
            }
        }
        fCount = maximumDigits;
    }

    // Eliminate trailing zeros.
    while (fCount > 1 && fDigits[fCount-1] == kZero) {
        --fCount;
    }
}

/**
 * Return true if truncating the representation to the given number
 * of digits will result in an increment to the last digit.  This
 * method implements half-even rounding, the default rounding mode.
 * [bnf]
 * @param maximumDigits the number of digits to keep, from 0 to
 * <code>count-1</code>.  If 0, then all digits are rounded away, and
 * this method returns true if a one should be generated (e.g., formatting
 * 0.09 with "#.#").
 * @return true if digit <code>maximumDigits-1</code> should be
 * incremented
 */
UBool DigitList::shouldRoundUp(int32_t maximumDigits) {
    // Implement IEEE half-even rounding
    if (fDigits[maximumDigits] == '5' ) {
        for (int i=maximumDigits+1; i<fCount; ++i) {
            if (fDigits[i] != kZero) {
                return TRUE;
            }
        }
        return maximumDigits > 0 && (fDigits[maximumDigits-1] % 2 != 0);
    }
    return (fDigits[maximumDigits] > '5');
}

// -------------------------------------

// In the Java implementation, we need a separate set(long) because 64-bit longs
// have too much precision to fit into a 64-bit double.  In C++, longs can just
// be passed to set(double) as long as they are 32 bits in size.  We currently
// don't implement 64-bit longs in C++, although the code below would work for
// that with slight modifications. [LIU]
/*
void
DigitList::set(long source)
{
    // handle the special case of zero using a standard exponent of 0.
    // mathematically, the exponent can be any value.
    if (source == 0)
    {
        fcount = 0;
        fDecimalAt = 0;
        return;
    }

    // we don't accept negative numbers, with the exception of long_min.
    // long_min is treated specially by being represented as long_max+1,
    // which is actually an impossible signed long value, so there is no
    // ambiguity.  we do this for convenience, so digitlist can easily
    // represent the digits of a long.
    bool islongmin = (source == long_min);
    if (islongmin)
    {
        source = -(source + 1); // that is, long_max
        islongmin = true;
    }
    sprintf(fdigits, "%d", source);

    // now we need to compute the exponent.  it's easy in this case; it's
    // just the same as the count.  e.g., 0.123 * 10^3 = 123.
    fcount = strlen(fdigits);
    fDecimalAt = fcount;

    // here's how we represent long_max + 1.  note that we always know
    // that the last digit of long_max will not be 9, because long_max
    // is of the form (2^n)-1.
    if (islongmin)
        ++fdigits[fcount-1];

    // finally, we trim off trailing zeros.  we don't alter fDecimalAt,
    // so this has no effect on the represented value.  we know the first
    // digit is non-zero (see code above), so we only have to check down
    // to fdigits[1].
    while (fcount > 1 && fdigits[fcount-1] == kzero)
        --fcount;
}
*/

/**
 * Return true if this object represents the value zero.  Anything with
 * no digits, or all zero digits, is zero, regardless of fDecimalAt.
 */
UBool
DigitList::isZero() const
{
    for (int32_t i=0; i<fCount; ++i)
        if (fDigits[i] != kZero)
            return FALSE;
    return TRUE;
}

/**
 * We represent LONG_MIN internally as LONG_MAX + 1.  This is actually an impossible
 * value, for positive long integers, so we are safe in doing so.
 */
/* // This code is unused.
UBool
DigitList::isLONG_MIN() const
{
//    initializeLONG_MIN_REP();

    if (fCount != LONG_MIN_REP_LENGTH)
        return FALSE;

    for (int32_t i = 0; i < LONG_MIN_REP_LENGTH; ++i)
    {
        if (fDigits[i] != LONG_MIN_REP[i+1])
            return FALSE;
    }

    return TRUE;
}
*/

// Initialize the LONG_MIN representation buffer.  Note that LONG_MIN
// is stored as LONG_MAX+1 (LONG_MIN without the negative sign).

/*void
DigitList::initializeLONG_MIN_REP()
{
    if (LONG_MIN_REP_LENGTH == 0)
    {
        char buf[LONG_DIGITS];
        sprintf(buf, "%d", INT32_MIN);
        LONG_MIN_REP_LENGTH = strlen(buf) - 1;
        // assert(LONG_MIN_REP_LENGTH == LONG_DIGITS);
        for (int32_t i=1; i<=LONG_MIN_REP_LENGTH; ++i)
            LONG_MIN_REP[i-1] = buf[i];
    }
}*/

U_NAMESPACE_END

//eof

--- NEW FILE: digitlst.h ---
/*
******************************************************************************
*
*   Copyright (C) 1997-2003, International Business Machines
*   Corporation and others.  All Rights Reserved.
*
******************************************************************************
*
* File DIGITLST.H
*
* Modification History:
*
*   Date        Name        Description
*   02/25/97    aliu        Converted from java.
*   03/21/97    clhuang     Updated per C++ implementation.
*   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
*   09/09/97    aliu        Adapted for exponential notation support.
*   08/02/98    stephen     Added nearest/even rounding
*   06/29/99    stephen     Made LONG_DIGITS a macro to satisfy SUN compiler
*   07/09/99    stephen     Removed kMaxCount (unused, for HP compiler)
******************************************************************************
*/
 
#ifndef DIGITLST_H
#define DIGITLST_H
 
#include "unicode/utypes.h"
#include "unicode/uobject.h"
#include <float.h>

// Decimal digits in a 64-bit int
//#define LONG_DIGITS 19 
#define INT64_DIGITS 19

typedef enum EDigitListValues {
    MAX_DBL_DIGITS = DBL_DIG,
	MAX_I64_DIGITS = INT64_DIGITS,
	MAX_DIGITS = MAX_I64_DIGITS,
    MAX_EXPONENT = DBL_DIG,
    DIGIT_PADDING = 3,

     // "+." + fDigits + "e" + fDecimalAt
    MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT
} EDigitListValues;

U_NAMESPACE_BEGIN

/**
 * Digit List utility class. Private to DecimalFormat.  Handles the transcoding
 * between numeric values and strings of characters.  Only handles
 * non-negative numbers.  The division of labor between DigitList and
 * DecimalFormat is that DigitList handles the radix 10 representation
 * issues; DecimalFormat handles the locale-specific issues such as
 * positive/negative, grouping, decimal point, currency, and so on.
 * <P>
 * A DigitList is really a representation of a floating point value.
 * It may be an integer value; we assume that a double has sufficient
 * precision to represent all digits of a long.
 * <P>
 * The DigitList representation consists of a string of characters,
 * which are the digits radix 10, from '0' to '9'.  It also has a radix
 * 10 exponent associated with it.  The value represented by a DigitList
 * object can be computed by mulitplying the fraction f, where 0 <= f < 1,
 * derived by placing all the digits of the list to the right of the
 * decimal point, by 10^exponent.
 */
class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy
public:
    DigitList();
    ~DigitList();

    /* copy constructor
     * @param DigitList The object to be copied.
     * @return the newly created object. 
     */
    DigitList(const DigitList&); // copy constructor

    /* assignment operator
     * @param DigitList The object to be copied.
     * @return the newly created object.
     */
    DigitList& operator=(const DigitList&);  // assignment operator

    /**
     * Return true if another object is semantically equal to this one.
     * @param other The DigitList to be compared for equality
     * @return true if another object is semantically equal to this one.
     * return false otherwise.
     */
    UBool operator==(const DigitList& other) const;

    /**
     * Return true if another object is semantically unequal to this one.
     * @param other The DigitList to  be compared for inequality
     * @return true if another object is semantically unequal to this one.
     * return false otherwise.
     */
    UBool operator!=(const DigitList& other) const { return !operator==(other); }

    /**
     * Clears out the digits.
     * Use before appending them.
     * Typically, you set a series of digits with append, then at the point
     * you hit the decimal point, you set myDigitList.fDecimalAt = myDigitList.fCount;
     * then go on appending digits.
     */
    void clear(void);

    /**
     * Appends digits to the list. Ignores all digits beyond the first DBL_DIG,
     * since they are not significant for either longs or doubles.
     * @param digit The digit to be appended.
     */
    inline void append(char digit);

    /**
     * Utility routine to get the value of the digit list
     * Returns 0.0 if zero length.
     * @return the value of the digit list.
     */
    double getDouble(void);

    /**
     * Utility routine to get the value of the digit list
     * Make sure that fitsIntoLong() is called before calling this function.
     * Returns 0 if zero length.
     * @return the value of the digit list, return 0 if it is zero length
     */
    int32_t getLong(void);

    /**
     * Utility routine to get the value of the digit list
     * Make sure that fitsIntoInt64() is called before calling this function.
     * Returns 0 if zero length.
     * @return the value of the digit list, return 0 if it is zero length
     */
    int64_t getInt64(void);

    /**
     * Return true if the number represented by this object can fit into
     * a long.
     * @param ignoreNegativeZero True if negative zero is ignored.
     * @return true if the number represented by this object can fit into
     * a long, return false otherwise.
     */
    UBool fitsIntoLong(UBool ignoreNegativeZero);

    /**
     * Return true if the number represented by this object can fit into
     * an int64_t.
     * @param ignoreNegativeZero True if negative zero is ignored.
     * @return true if the number represented by this object can fit into
     * a long, return false otherwise.
     */
    UBool fitsIntoInt64(UBool ignoreNegativeZero);

    /**
     * Utility routine to set the value of the digit list from a double
     * Input must be non-negative, and must not be Inf, -Inf, or NaN.
     * The maximum fraction digits helps us round properly.
     * @param source The value to be set
     * @param maximunDigits The maximum number of digits to be shown
     * @param fixedPoint True if the point is fixed
     */
    void set(double source, int32_t maximumDigits, UBool fixedPoint = TRUE);

    /**
     * Utility routine to set the value of the digit list from a long.
     * If a non-zero maximumDigits is specified, no more than that number of
     * significant digits will be produced.
     * @param source The value to be set
     * @param maximunDigits The maximum number of digits to be shown
     */
    void set(int32_t source, int32_t maximumDigits = 0);

    /**
     * Utility routine to set the value of the digit list from an int64.
     * If a non-zero maximumDigits is specified, no more than that number of
     * significant digits will be produced.
     * @param source The value to be set
     * @param maximunDigits The maximum number of digits to be shown
     */
    void set(int64_t source, int32_t maximumDigits = 0);

    /**
     * Return true if this is a representation of zero.
     * @return true if this is a representation of zero.
     */
    UBool isZero(void) const;

    /**
     * Return true if this is a representation of LONG_MIN.  You must use
     * this method to determine if this is so; you cannot check directly,
     * because a special format is used to handle this.
     */
    // This code is unused.
    //UBool isLONG_MIN(void) const;

public:
    /**
     * These data members are intentionally public and can be set directly.
     *<P>
     * The value represented is given by placing the decimal point before
     * fDigits[fDecimalAt].  If fDecimalAt is < 0, then leading zeros between
     * the decimal point and the first nonzero digit are implied.  If fDecimalAt
     * is > fCount, then trailing zeros between the fDigits[fCount-1] and the
     * decimal point are implied.
     * <P>
     * Equivalently, the represented value is given by f * 10^fDecimalAt.  Here
     * f is a value 0.1 <= f < 1 arrived at by placing the digits in fDigits to
     * the right of the decimal.
     * <P>
     * DigitList is normalized, so if it is non-zero, fDigits[0] is non-zero.  We
     * don't allow denormalized numbers because our exponent is effectively of
     * unlimited magnitude.  The fCount value contains the number of significant
     * digits present in fDigits[].
     * <P>
     * Zero is represented by any DigitList with fCount == 0 or with each fDigits[i]
     * for all i <= fCount == '0'.
     */
    int32_t     fDecimalAt;
    int32_t     fCount;
    UBool       fIsPositive;
    char        *fDigits;

private:

    /* One character before fDigits for the decimal*/
    char        fDecimalDigits[MAX_DEC_DIGITS + 1];

    /**
     * Round the representation to the given number of digits.
     * @param maximumDigits The maximum number of digits to be shown.
     * Upon return, count will be less than or equal to maximumDigits.
     */
    void round(int32_t maximumDigits);

    /**
     * Initializes the buffer that records the mimimum long value.
     * @param maximumDigits The maximum number of digits to be shown.
     */
    /*static void initializeLONG_MIN_REP(void);*/

    UBool shouldRoundUp(int32_t maximumDigits);
};
 
// -------------------------------------
// Appends the digit to the digit list if it's not out of scope.
// Ignores the digit, otherwise.

inline void
DigitList::append(char digit)
{
    // Ignore digits which exceed the precision we can represent
    if (fCount < MAX_DIGITS)
        fDigits[fCount++] = digit;
}

U_NAMESPACE_END
#endif // _DIGITLST

//eof

--- NEW FILE: gregoimp.cpp ---
/*
**********************************************************************
* Copyright (c) 2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: September 2 2003
* Since: ICU 2.8
**********************************************************************
*/
#include "gregoimp.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/ucal.h"

int32_t Math::floorDivide(int32_t numerator, int32_t denominator) {
    return (numerator >= 0) ?
        numerator / denominator : ((numerator + 1) / denominator) - 1;
}

int32_t Math::floorDivide(double numerator, int32_t denominator,
                          int32_t& remainder) {
    double quotient;
    quotient = uprv_floor(numerator / denominator);
    remainder = (int32_t) (numerator - (quotient * denominator));
    return (int32_t) quotient;
}

const int32_t JULIAN_1_CE    = 1721426; // January 1, 1 CE Gregorian
const int32_t JULIAN_1970_CE = 2440588; // January 1, 1970 CE Gregorian

const int16_t Grego::DAYS_BEFORE[24] =
    {0,31,59,90,120,151,181,212,243,273,304,334,
     0,31,60,91,121,152,182,213,244,274,305,335};

const int8_t Grego::MONTH_LENGTH[24] =
    {31,28,31,30,31,30,31,31,30,31,30,31,
     31,29,31,30,31,30,31,31,30,31,30,31};

double Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) {

    int32_t y = year - 1;

    double julian = 365 * y + Math::floorDivide(y, 4) + (JULIAN_1_CE - 3) + // Julian cal
        Math::floorDivide(y, 400) - Math::floorDivide(y, 100) + 2 + // => Gregorian cal
        DAYS_BEFORE[month + (isLeapYear(year) ? 12 : 0)] + dom; // => month/dom

    return julian - JULIAN_1970_CE; // JD => epoch day
}

void Grego::dayToFields(double day, int32_t& year, int32_t& month,
                        int32_t& dom, int32_t& dow, int32_t& doy) {

    // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
    day += JULIAN_1970_CE - JULIAN_1_CE;

    // Convert from the day number to the multiple radix
    // representation.  We use 400-year, 100-year, and 4-year cycles.
    // For example, the 4-year cycle has 4 years + 1 leap day; giving
    // 1461 == 365*4 + 1 days.
    int32_t n400 = Math::floorDivide(day, 146097, doy); // 400-year cycle length
    int32_t n100 = Math::floorDivide(doy, 36524, doy); // 100-year cycle length
    int32_t n4   = Math::floorDivide(doy, 1461, doy); // 4-year cycle length
    int32_t n1   = Math::floorDivide(doy, 365, doy);
    year = 400*n400 + 100*n100 + 4*n4 + n1;
    if (n100 == 4 || n1 == 4) {
        doy = 365; // Dec 31 at end of 4- or 400-year cycle
    } else {
        ++year;
    }
    
    UBool isLeap = isLeapYear(year);
    
    // Gregorian day zero is a Monday.
    dow = (int32_t) uprv_fmod(day + 1, 7);
    dow += (dow < 0) ? (UCAL_SUNDAY + 7) : UCAL_SUNDAY;

    // Common Julian/Gregorian calculation
    int32_t correction = 0;
    int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
    if (doy >= march1) {
        correction = isLeap ? 1 : 2;
    }
    month = (12 * (doy + correction) + 6) / 367; // zero-based month
    dom = doy - DAYS_BEFORE[month + (isLeap ? 12 : 0)] + 1; // one-based DOM
    doy++; // one-based doy
}

#endif
//eof

--- NEW FILE: gregoimp.h ---
/*
**********************************************************************
* Copyright (c) 2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: September 2 2003
* Since: ICU 2.8
**********************************************************************
*/
#ifndef GREGOIMP_H
#define GREGOIMP_H
#if !UCONFIG_NO_FORMATTING

#include "unicode/utypes.h"

U_NAMESPACE_BEGIN

/**
 * A utility class providing mathematical functions used by time zone
 * and calendar code.  Do not instantiate.
 */
class U_I18N_API Math {
 public:
    /**
     * Divide two integers, returning the floor of the quotient.
     * Unlike the built-in division, this is mathematically
     * well-behaved.  E.g., <code>-1/4</code> => 0 but
     * <code>floorDivide(-1,4)</code> => -1.
     * @param numerator the numerator
     * @param denominator a divisor which must be != 0
     * @return the floor of the quotient
     */
    static int32_t floorDivide(int32_t numerator, int32_t denominator);

    /**
     * Divide two numbers, returning the floor of the quotient.
     * Unlike the built-in division, this is mathematically
     * well-behaved.  E.g., <code>-1/4</code> => 0 but
     * <code>floorDivide(-1,4)</code> => -1.
     * @param numerator the numerator
     * @param denominator a divisor which must be != 0
     * @return the floor of the quotient
     */
    static inline double floorDivide(double numerator, double denominator);

    /**
     * Divide two numbers, returning the floor of the quotient and
     * the modulus remainder.  Unlike the built-in division, this is
     * mathematically well-behaved.  E.g., <code>-1/4</code> => 0 and
     * <code>-1%4</code> => -1, but <code>floorDivide(-1,4)</code> =>
     * -1 with <code>remainder</code> => 3.  NOTE: If numerator is
     * too large, the returned quotient may overflow.
     * @param numerator the numerator
     * @param denominator a divisor which must be != 0
     * @param remainder output parameter to receive the
     * remainder. Unlike <code>numerator % denominator</code>, this
     * will always be non-negative, in the half-open range <code>[0,
     * |denominator|)</code>.
     * @return the floor of the quotient
     */
    static int32_t floorDivide(double numerator, int32_t denominator,
                               int32_t& remainder);
};

// Useful millisecond constants
#define kOneDay    (1.0 * U_MILLIS_PER_DAY)       //  86,400,000
#define kOneHour   (60*60*1000)
#define kOneMinute 60000
#define kOneSecond 1000
#define kOneMillisecond  1
#define kOneWeek   (7.0 * kOneDay) // 604,800,000

// Epoch constants
#define kJan1_1JulianDay  1721426 // January 1, year 1 (Gregorian)

#define kEpochStartAsJulianDay  2440588 // January 1, 1970 (Gregorian)

#define kEpochYear              1970


#define kEarliestViableMillis  -185331720384000000.0  // minimum representable by julian day  -1e17

#define kLatestViableMillis     185753453990400000.0  // max representable by julian day      +1e17



/**
 * A utility class providing proleptic Gregorian calendar functions
 * used by time zone and calendar code.  Do not instantiate.
 *
 * Note:  Unlike GregorianCalendar, all computations performed by this
 * class occur in the pure proleptic GregorianCalendar.
 */
class U_I18N_API Grego {
 public:
    /**
     * Return TRUE if the given year is a leap year.
     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
     * @return TRUE if the year is a leap year
     */
    static inline UBool isLeapYear(int32_t year);

    /**
     * Return the number of days in the given month.
     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
     * @param month 0-based month, with 0==Jan
     * @return the number of days in the given month
     */
    static inline int8_t monthLength(int32_t year, int32_t month);

    /**
     * Return the length of a previous month of the Gregorian calendar.
     * @param y the extended year
     * @param m the 0-based month number
     * @return the number of days in the month previous to the given month
     */
    static inline int8_t previousMonthLength(int y, int m);

    /**
     * Convert a year, month, and day-of-month, given in the proleptic
     * Gregorian calendar, to 1970 epoch days.
     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
     * @param month 0-based month, with 0==Jan
     * @param dom 1-based day of month
     * @return the day number, with day 0 == Jan 1 1970
     */
    static double fieldsToDay(int32_t year, int32_t month, int32_t dom);
    
    /**
     * Convert a 1970-epoch day number to proleptic Gregorian year,
     * month, day-of-month, and day-of-week.
     * @param day 1970-epoch day (integral value)
     * @param year output parameter to receive year
     * @param month output parameter to receive month (0-based, 0==Jan)
     * @param dom output parameter to receive day-of-month (1-based)
     * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
     * @param doy output parameter to receive day-of-year (1-based)
     */
    static void dayToFields(double day, int32_t& year, int32_t& month,
                            int32_t& dom, int32_t& dow, int32_t& doy);

    /**
     * Convert a 1970-epoch day number to proleptic Gregorian year,
     * month, day-of-month, and day-of-week.
     * @param day 1970-epoch day (integral value)
     * @param year output parameter to receive year
     * @param month output parameter to receive month (0-based, 0==Jan)
     * @param dom output parameter to receive day-of-month (1-based)
     * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
     */
    static inline void dayToFields(double day, int32_t& year, int32_t& month,
                                   int32_t& dom, int32_t& dow);

    /**
     * Converts Julian day to time as milliseconds.
     * @param julian the given Julian day number.
     * @return time as milliseconds.
     * @internal
     */
    static inline double julianDayToMillis(int32_t julian);

    /**
     * Converts time as milliseconds to Julian day.
     * @param millis the given milliseconds.
     * @return the Julian day number.
     * @internal
     */
    static inline int32_t millisToJulianDay(double millis);

    /** 
     * Calculates the Gregorian day shift value for an extended year.
     * @param eyear Extended year 
     * @returns number of days to ADD to Julian in order to convert from J->G
     */
    static inline int32_t gregorianShift(int32_t eyear);

 private:
    static const int16_t DAYS_BEFORE[24];
    static const int8_t MONTH_LENGTH[24];
};

inline double Math::floorDivide(double numerator, double denominator) {
    return uprv_floor(numerator / denominator);
}

inline UBool Grego::isLeapYear(int32_t year) {
    // year&0x3 == year%4
    return ((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0));
}

inline int8_t
Grego::monthLength(int32_t year, int32_t month) {
    return MONTH_LENGTH[month + isLeapYear(year)?12:0];
}

inline int8_t
Grego::previousMonthLength(int y, int m) {
  return (m > 0) ? monthLength(y, m-1) : 31;
}

inline void Grego::dayToFields(double day, int32_t& year, int32_t& month,
                               int32_t& dom, int32_t& dow) {
  int32_t doy_unused;
  dayToFields(day,year,month,dom,dow,doy_unused);
}

inline double Grego::julianDayToMillis(int32_t julian)
{
  return (julian - kEpochStartAsJulianDay) * kOneDay;
}

inline int32_t Grego::millisToJulianDay(double millis) {
  return (int32_t) (kEpochStartAsJulianDay + Math::floorDivide(millis, (double)kOneDay));
}

inline int32_t Grego::gregorianShift(int32_t eyear) {
  int32_t y = eyear-1;
  int32_t gregShift = Math::floorDivide(y, 400) - Math::floorDivide(y, 100) + 2;
  return gregShift;
}


U_NAMESPACE_END

#endif // !UCONFIG_NO_FORMATTING
#endif // GREGOIMP_H

//eof

--- NEW FILE: hebrwcal.cpp ---
/*
 * Copyright (C) 2003, International Business Machines Corporation
 * and others. All Rights Reserved.
 ******************************************************************************
 *
 * File HEBRWCAL.H
 *
 * Modification History:
 *
 *   Date        Name        Description
 *   12/03/2003  srl         ported from java HebrewCalendar
 *****************************************************************************
 */

#include "hebrwcal.h"

#if !UCONFIG_NO_FORMATTING

#include "mutex.h"
#include <float.h>
#include "gregoimp.h" // Math
#include "astro.h" // CalendarAstronomer
#include "uhash.h"
#include "ucln_in.h"

U_NAMESPACE_BEGIN
// Hebrew Calendar implementation

/**
 * The absolute date, in milliseconds since 1/1/1970 AD, Gregorian,
 * of the start of the Hebrew calendar.  In order to keep this calendar's
 * time of day in sync with that of the Gregorian calendar, we use
 * midnight, rather than sunset the day before.
 */
static const double EPOCH_MILLIS = -180799862400000.; // 1/1/1 HY

static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = {
  // Minimum  Greatest    Least  Maximum
  //           Minimum  Maximum
  {        0,        0,       0,       0 }, // ERA
  {        1,        1, 5000000, 5000000 }, // YEAR
  {        0,        0,      12,      12 }, // MONTH
  {        1,        1,      51,      56 }, // WEEK_OF_YEAR
  {        0,        0,       5,       6 }, // WEEK_OF_MONTH
  {        1,        1,      29,      30 }, // DAY_OF_MONTH
  {        1,        1,     353,     385 }, // DAY_OF_YEAR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
  {       -1,       -1,       4,       6 }, // DAY_OF_WEEK_IN_MONTH
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1/*                                  */}, // AM_PM
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
  { -5000001, -5000001, 5000001, 5000001 }, // YEAR_WOY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
  { -5000000, -5000000, 5000000, 5000000 }, // EXTENDED_YEAR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
};

/**
 * The lengths of the Hebrew months.  This is complicated, because there
 * are three different types of years, or six if you count leap years.
 * Due to the rules for postponing the start of the year to avoid having
 * certain holidays fall on the sabbath, the year can end up being three
 * different lengths, called "deficient", "normal", and "complete".
 */
static const int32_t MONTH_LENGTH[][3] = {
  // Deficient  Normal     Complete
  {   30,         30,         30     },           //Tishri
  {   29,         29,         30     },           //Heshvan
  {   29,         30,         30     },           //Kislev
  {   29,         29,         29     },           //Tevet
  {   30,         30,         30     },           //Shevat
  {   30,         30,         30     },           //Adar I (leap years only)
  {   29,         29,         29     },           //Adar
  {   30,         30,         30     },           //Nisan
  {   29,         29,         29     },           //Iyar
  {   30,         30,         30     },           //Sivan
  {   29,         29,         29     },           //Tammuz
  {   30,         30,         30     },           //Av
  {   29,         29,         29     },           //Elul
};

/**
 * The cumulative # of days to the end of each month in a non-leap year
 * Although this can be calculated from the MONTH_LENGTH table,
 * keeping it around separately makes some calculations a lot faster
 */

static const int32_t MONTH_START[][3] = {
  // Deficient  Normal     Complete
  {    0,          0,          0  },          // (placeholder)
  {   30,         30,         30  },          // Tishri
  {   59,         59,         60  },          // Heshvan
  {   88,         89,         90  },          // Kislev
  {  117,        118,        119  },          // Tevet
  {  147,        148,        149  },          // Shevat
  {  147,        148,        149  },          // (Adar I placeholder)
  {  176,        177,        178  },          // Adar
  {  206,        207,        208  },          // Nisan
  {  235,        236,        237  },          // Iyar
  {  265,        266,        267  },          // Sivan
  {  294,        295,        296  },          // Tammuz
  {  324,        325,        326  },          // Av
  {  353,        354,        355  },          // Elul
};

/**
 * The cumulative # of days to the end of each month in a leap year
 */
static const int32_t  LEAP_MONTH_START[][3] = {
  // Deficient  Normal     Complete
  {    0,          0,          0  },          // (placeholder)
  {   30,         30,         30  },          // Tishri
  {   59,         59,         60  },          // Heshvan
  {   88,         89,         90  },          // Kislev
  {  117,        118,        119  },          // Tevet
  {  147,        148,        149  },          // Shevat
  {  177,        178,        179  },          // Adar I
  {  206,        207,        208  },          // Adar II
  {  236,        237,        238  },          // Nisan
  {  265,        266,        267  },          // Iyar
  {  295,        296,        297  },          // Sivan
  {  324,        325,        326  },          // Tammuz
  {  354,        355,        356  },          // Av
  {  383,        384,        385  },          // Elul
};

//-------------------------------------------------------------------------
// Data Members...
//-------------------------------------------------------------------------

static CalendarCache *gCache =  NULL;

//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------

/**
 * Constructs a default <code>HebrewCalendar</code> using the current time
 * in the default time zone with the default locale.
 * @internal
 */
HebrewCalendar::HebrewCalendar(const Locale& aLocale, UErrorCode& success)
  :   Calendar(TimeZone::createDefault(), aLocale, success)

{
  setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
}


HebrewCalendar::~HebrewCalendar() {
}

const char *HebrewCalendar::getType() const {
  return "hebrew";
}

Calendar* HebrewCalendar::clone() const {
  return new HebrewCalendar(*this);
}

HebrewCalendar::HebrewCalendar(const HebrewCalendar& other) : Calendar(other) {
}


//-------------------------------------------------------------------------
// Rolling and adding functions overridden from Calendar
//
// These methods call through to the default implementation in IBMCalendar
// for most of the fields and only handle the unusual ones themselves.
//-------------------------------------------------------------------------

/**
 * Add a signed amount to a specified field, using this calendar's rules.
 * For example, to add three days to the current date, you can call
 * <code>add(Calendar.DATE, 3)</code>. 
 * <p>
 * When adding to certain fields, the values of other fields may conflict and
 * need to be changed.  For example, when adding one to the {@link #MONTH MONTH} field
 * for the date "30 Av 5758", the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
 * must be adjusted so that the result is "29 Elul 5758" rather than the invalid
 * "30 Elul 5758".
 * <p>
 * This method is able to add to
 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
 * and {@link #ZONE_OFFSET ZONE_OFFSET}.
 * <p>
 * <b>Note:</b> You should always use {@link #roll roll} and add rather
 * than attempting to perform arithmetic operations directly on the fields
 * of a <tt>HebrewCalendar</tt>.  Since the {@link #MONTH MONTH} field behaves
 * discontinuously in non-leap years, simple arithmetic can give invalid results.
 * <p>
 * @param field     the time field.
 * @param amount    the amount to add to the field.
 *
 * @exception   IllegalArgumentException if the field is invalid or refers
 *              to a field that cannot be handled by this method.
 * @internal
 */
void HebrewCalendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status)
{
  if(U_FAILURE(status)) {
    return;
  }
  switch (field) {
  case UCAL_MONTH: 
    {
      // We can't just do a set(MONTH, get(MONTH) + amount).  The
      // reason is ADAR_1.  Suppose amount is +2 and we land in
      // ADAR_1 -- then we have to bump to ADAR_2 aka ADAR.  But
      // if amount is -2 and we land in ADAR_1, then we have to
      // bump the other way -- down to SHEVAT.  - Alan 11/00
      int32_t month = get(UCAL_MONTH, status);
      int32_t year = get(UCAL_YEAR, status);
      UBool acrossAdar1;
      if (amount > 0) {
        acrossAdar1 = (month < ADAR_1); // started before ADAR_1?
        month += amount;
        for (;;) {
          if (acrossAdar1 && month>=ADAR_1 && !isLeapYear(year)) {
            ++month;
          }
          if (month <= ELUL) {
            break;
          }
          month -= ELUL+1;
          ++year;
          acrossAdar1 = TRUE;
        }
      } else {
        acrossAdar1 = (month > ADAR_1); // started after ADAR_1?
        month += amount;
        for (;;) {
          if (acrossAdar1 && month<=ADAR_1 && !isLeapYear(year)) {
            --month;
          }
          if (month >= 0) {
            break;
          }
          month += ELUL+1;
          --year;
          acrossAdar1 = TRUE;
        }
      }
      set(UCAL_MONTH, month);
      set(UCAL_YEAR, year);
      pinField(UCAL_DAY_OF_MONTH, status);
      break;
    }
            
  default:
    Calendar::add(field, amount, status);
    break;
  }
}

/**
 * Rolls (up/down) a specified amount time on the given field.  For
 * example, to roll the current date up by three days, you can call
 * <code>roll(Calendar.DATE, 3)</code>.  If the
 * field is rolled past its maximum allowable value, it will "wrap" back
 * to its minimum and continue rolling.  
 * For example, calling <code>roll(Calendar.DATE, 10)</code>
 * on a Hebrew calendar set to "25 Av 5758" will result in the date "5 Av 5758".
 * <p>
 * When rolling certain fields, the values of other fields may conflict and
 * need to be changed.  For example, when rolling the {@link #MONTH MONTH} field
 * upward by one for the date "30 Av 5758", the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
 * must be adjusted so that the result is "29 Elul 5758" rather than the invalid
 * "30 Elul".
 * <p>
 * This method is able to roll
 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
 * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
 * additional fields in their overrides of <code>roll</code>.
 * <p>
 * <b>Note:</b> You should always use roll and {@link #add add} rather
 * than attempting to perform arithmetic operations directly on the fields
 * of a <tt>HebrewCalendar</tt>.  Since the {@link #MONTH MONTH} field behaves
 * discontinuously in non-leap years, simple arithmetic can give invalid results.
 * <p>
 * @param field     the time field.
 * @param amount    the amount by which the field should be rolled.
 *
 * @exception   IllegalArgumentException if the field is invalid or refers
 *              to a field that cannot be handled by this method.
 * @internal
 */
void HebrewCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status)
{
  if(U_FAILURE(status)) {
    return;
  }
  switch (field) {
  case UCAL_MONTH:
    {
      int32_t month = get(UCAL_MONTH, status);
      int32_t year = get(UCAL_YEAR, status);
      
      UBool leapYear = isLeapYear(year);
      int32_t yearLength = monthsInYear(year);
      int32_t newMonth = month + (amount % yearLength);
      //
      // If it's not a leap year and we're rolling past the missing month
      // of ADAR_1, we need to roll an extra month to make up for it.
      //
      if (!leapYear) {
        if (amount > 0 && month < ADAR_1 && newMonth >= ADAR_1) {
          newMonth++;
        } else if (amount < 0 && month > ADAR_1 && newMonth <= ADAR_1) {
          newMonth--;
        }
      }
      set(UCAL_MONTH, (newMonth + 13) % 13);
      pinField(UCAL_DAY_OF_MONTH, status);
      return;
    }
  default:
    Calendar::roll(field, amount, status);
  }
}

void HebrewCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status) {
  roll((UCalendarDateFields)field, amount, status);
}

//-------------------------------------------------------------------------
// Support methods
//-------------------------------------------------------------------------

// Hebrew date calculations are performed in terms of days, hours, and
// "parts" (or halakim), which are 1/1080 of an hour, or 3 1/3 seconds.
static const int32_t HOUR_PARTS = 1080;
static const int32_t DAY_PARTS  = 24*HOUR_PARTS;

// An approximate value for the length of a lunar month.
// It is used to calculate the approximate year and month of a given
// absolute date.
static const int32_t  MONTH_DAYS = 29;
static const int32_t MONTH_FRACT = 12*HOUR_PARTS + 793;
static const int32_t MONTH_PARTS = MONTH_DAYS*DAY_PARTS + MONTH_FRACT;
    
// The time of the new moon (in parts) on 1 Tishri, year 1 (the epoch)
// counting from noon on the day before.  BAHARAD is an abbreviation of
// Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204).
static const int32_t BAHARAD = 11*HOUR_PARTS + 204;

/**
 * Finds the day # of the first day in the given Hebrew year.
 * To do this, we want to calculate the time of the Tishri 1 new moon
 * in that year.
 * <p>
 * The algorithm here is similar to ones described in a number of
 * references, including:
 * <ul>
 * <li>"Calendrical Calculations", by Nachum Dershowitz & Edward Reingold,
 *     Cambridge University Press, 1997, pages 85-91.
 *
 * <li>Hebrew Calendar Science and Myths,
 *     <a href="http://www.geocities.com/Athens/1584/">
 *     http://www.geocities.com/Athens/1584/</a>
 *
 * <li>The Calendar FAQ,
 *      <a href="http://www.faqs.org/faqs/calendars/faq/">
 *      http://www.faqs.org/faqs/calendars/faq/</a>
 * </ul>
 */
int32_t HebrewCalendar::startOfYear(int32_t year, UErrorCode &status)
{
  int32_t day = CalendarCache::get(&gCache, year, status);
  
  if (day == 0) {
    int32_t months = (235 * year - 234) / 19;           // # of months before year

    int32_t frac = months * MONTH_FRACT + BAHARAD;     // Fractional part of day #
    day  = months * 29 + (frac / DAY_PARTS);        // Whole # part of calculation
    frac = frac % DAY_PARTS;                        // Time of day

    int32_t wd = (day % 7);                        // Day of week (0 == Monday)
    
    if (wd == 2 || wd == 4 || wd == 6) {
      // If the 1st is on Sun, Wed, or Fri, postpone to the next day
      day += 1;
      wd = (day % 7);
    }
    if (wd == 1 && frac > 15*HOUR_PARTS+204 && !isLeapYear(year) ) {
      // If the new moon falls after 3:11:20am (15h204p from the previous noon)
      // on a Tuesday and it is not a leap year, postpone by 2 days.
      // This prevents 356-day years.
      day += 2;
    }
    else if (wd == 0 && frac > 21*HOUR_PARTS+589 && isLeapYear(year-1) ) {
      // If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon)
      // on a Monday and *last* year was a leap year, postpone by 1 day.
      // Prevents 382-day years.
      day += 1;
    }
    CalendarCache::put(&gCache, year, day, status);
  }
  return day;
}

/**
 * Find the day of the week for a given day
 *
 * @param day   The # of days since the start of the Hebrew calendar,
 *              1-based (i.e. 1/1/1 AM is day 1).
 */
int32_t HebrewCalendar::absoluteDayToDayOfWeek(int32_t day)
{
  // We know that 1/1/1 AM is a Monday, which makes the math easy...
  return (day % 7) + 1;
}

/**
 * Returns the the type of a given year.
 *  0   "Deficient" year with 353 or 383 days
 *  1   "Normal"    year with 354 or 384 days
 *  2   "Complete"  year with 355 or 385 days
 */
int32_t HebrewCalendar::yearType(int32_t year) const
{
  int32_t yearLength = handleGetYearLength(year);

  if (yearLength > 380) {
    yearLength -= 30;        // Subtract length of leap month.
  }

  int type = 0;
  
  switch (yearLength) {
  case 353:
    type = 0; break;
  case 354:
    type = 1; break;
  case 355:
    type = 2; break;
  default:
    //throw new RuntimeException("Illegal year length " + yearLength + " in year " + year);
    type = 1;
  }
  return type;
}

/**
 * Determine whether a given Hebrew year is a leap year
 *
 * The rule here is that if (year % 19) == 0, 3, 6, 8, 11, 14, or 17.
 * The formula below performs the same test, believe it or not.
 */
UBool HebrewCalendar::isLeapYear(int32_t year) {
  //return (year * 12 + 17) % 19 >= 12;
  int32_t x = (year*12 + 17) % 19;
  return x >= ((x < 0) ? -7 : 12);
}

int32_t HebrewCalendar::monthsInYear(int32_t year) {
  return isLeapYear(year) ? 13 : 12;
}

//-------------------------------------------------------------------------
// Calendar framework
//-------------------------------------------------------------------------

/**
 * @internal
 */
int32_t HebrewCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
  return LIMITS[field][limitType];
}

/**
 * Returns the length of the given month in the given year
 * @internal
 */
int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
  switch (month) {
  case HESHVAN:
  case KISLEV:
    // These two month lengths can vary
    return MONTH_LENGTH[month][yearType(extendedYear)];
    
  default:
    // The rest are a fixed length
    return MONTH_LENGTH[month][0];
  }
}

/**
 * Returns the number of days in the given Hebrew year
 * @internal
 */
int32_t HebrewCalendar::handleGetYearLength(int32_t eyear) const {
  UErrorCode status = U_ZERO_ERROR;
  return startOfYear(eyear+1, status) - startOfYear(eyear, status);
}

//-------------------------------------------------------------------------
// Functions for converting from milliseconds to field values
//-------------------------------------------------------------------------

/**
 * Subclasses may override this method to compute several fields
 * specific to each calendar system.  These are:
 *
 * <ul><li>ERA
 * <li>YEAR
 * <li>MONTH
 * <li>DAY_OF_MONTH
 * <li>DAY_OF_YEAR
 * <li>EXTENDED_YEAR</ul>
 * 
 * Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields,
 * which will be set when this method is called.  Subclasses can
 * also call the getGregorianXxx() methods to obtain Gregorian
 * calendar equivalents for the given Julian day.
 *
 * <p>In addition, subclasses should compute any subclass-specific
 * fields, that is, fields from BASE_FIELD_COUNT to
 * getFieldCount() - 1.
 * @internal
 */
void HebrewCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
  int32_t d = julianDay - 347997;
  double m = ((d * (double)DAY_PARTS)/ (double) MONTH_PARTS);         // Months (approx)
  int32_t year = (int32_t)( ((19. * m + 234.) / 235.) + 1.);     // Years (approx)
  int32_t ys  = startOfYear(year, status);                   // 1st day of year
  int32_t dayOfYear = (d - ys);

  // Because of the postponement rules, it's possible to guess wrong.  Fix it.
  while (dayOfYear < 1) {
    year--;
    ys  = startOfYear(year, status);
    dayOfYear = (d - ys);
  }
  
  // Now figure out which month we're in, and the date within that month
  int32_t type = yearType(year);
  UBool isLeap = isLeapYear(year);

  int32_t month = 0;
  while (dayOfYear > (  isLeap ? LEAP_MONTH_START[month][type] : MONTH_START[month][type] ) ) {
    month++;
  }
  month--;
  int dayOfMonth = dayOfYear - (isLeap ? LEAP_MONTH_START[month][type] : MONTH_START[month][type]);
  
  internalSet(UCAL_ERA, 0);
  internalSet(UCAL_YEAR, year);
  internalSet(UCAL_EXTENDED_YEAR, year);
  internalSet(UCAL_MONTH, month);
  internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
  internalSet(UCAL_DAY_OF_YEAR, dayOfYear);       
}

//-------------------------------------------------------------------------
// Functions for converting from field values to milliseconds
//-------------------------------------------------------------------------

/**
 * @internal
 */
int32_t HebrewCalendar::handleGetExtendedYear() {
  int32_t year;
  if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
    year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
  } else {
    year = internalGet(UCAL_YEAR, 1); // Default to year 1
  }
  return year;
}

/**
 * Return JD of start of given month/year.
 * @internal
 */
int32_t HebrewCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/) const {
  UErrorCode status = U_ZERO_ERROR;
  // Resolve out-of-range months.  This is necessary in order to
  // obtain the correct year.  We correct to
  // a 12- or 13-month year (add/subtract 12 or 13, depending
  // on the year) but since we _always_ number from 0..12, and
  // the leap year determines whether or not month 5 (Adar 1)
  // is present, we allow 0..12 in any given year.
  while (month < 0) {
    month += monthsInYear(--eyear);
  }
  // Careful: allow 0..12 in all years
  while (month > 12) {
    month -= monthsInYear(eyear++);
  }
  
  int32_t day = startOfYear(eyear, status);
  
  if(U_FAILURE(status)) {
    return 0;
  }

  if (month != 0) {
    if (isLeapYear(eyear)) {
      day += LEAP_MONTH_START[month][yearType(eyear)];
    } else {
      day += MONTH_START[month][yearType(eyear)];
    }
  }
  
  return (int) (day + 347997);
}

UBool
HebrewCalendar::inDaylightTime(UErrorCode& status) const
{
// copied from GregorianCalendar
if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) 
  return FALSE;

    // Force an update of the state of the Calendar.
((HebrewCalendar*)this)->complete(status); // cast away const

return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
}

// default century
const UDate     HebrewCalendar::fgSystemDefaultCentury        = DBL_MIN;
const int32_t   HebrewCalendar::fgSystemDefaultCenturyYear    = -1;

UDate           HebrewCalendar::fgSystemDefaultCenturyStart       = DBL_MIN;
int32_t         HebrewCalendar::fgSystemDefaultCenturyStartYear   = -1;


UBool HebrewCalendar::haveDefaultCentury() const
{
  return TRUE;
}

UDate HebrewCalendar::defaultCenturyStart() const
{
  return internalGetDefaultCenturyStart();
}

int32_t HebrewCalendar::defaultCenturyStartYear() const
{
  return internalGetDefaultCenturyStartYear();
}

UDate
HebrewCalendar::internalGetDefaultCenturyStart() const
{
  // lazy-evaluate systemDefaultCenturyStart
  UBool needsUpdate;
  { 
    Mutex m;
    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
  }

  if (needsUpdate) {
    initializeSystemDefaultCentury();
  }

  // use defaultCenturyStart unless it's the flag value;
  // then use systemDefaultCenturyStart
  
  return fgSystemDefaultCenturyStart;
}

int32_t
HebrewCalendar::internalGetDefaultCenturyStartYear() const
{
  // lazy-evaluate systemDefaultCenturyStartYear
  UBool needsUpdate;
  { 
    Mutex m;
    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
  }

  if (needsUpdate) {
    initializeSystemDefaultCentury();
  }

  // use defaultCenturyStart unless it's the flag value;
  // then use systemDefaultCenturyStartYear
  
  return    fgSystemDefaultCenturyStartYear;
}

void
HebrewCalendar::initializeSystemDefaultCentury()
{
  // initialize systemDefaultCentury and systemDefaultCenturyYear based
  // on the current time.  They'll be set to 80 years before
  // the current time.
  // No point in locking as it should be idempotent.
  if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
  {
    UErrorCode status = U_ZERO_ERROR;
    Calendar *calendar = new HebrewCalendar(Locale("he@calendar=hebrew"),status);
    if (calendar != NULL && U_SUCCESS(status))
    {
      calendar->setTime(Calendar::getNow(), status);
      calendar->add(UCAL_YEAR, -80, status);
      UDate    newStart =  calendar->getTime(status);
      int32_t  newYear  =  calendar->get(UCAL_YEAR, status);
      {
        Mutex m;
        fgSystemDefaultCenturyStart = newStart;
        fgSystemDefaultCenturyStartYear = newYear;
      }
      delete calendar;
    }
    // We have no recourse upon failure unless we want to propagate the failure
    // out.
  }
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(HebrewCalendar);


U_NAMESPACE_END

U_CFUNC UBool calendar_hebrew_cleanup(void) {
  delete gCache;
  gCache = NULL;
  return TRUE;
}


#endif // UCONFIG_NO_FORMATTING


--- NEW FILE: hebrwcal.h ---
/*
* Copyright (C) 2003, International Business Machines Corporation and others. All Rights Reserved.
********************************************************************************
*
* File HEBRWCAL.H
*
* Modification History:
*
*   Date        Name        Description
*   05/13/2003  srl          copied from gregocal.h
*   11/26/2003  srl          copied from buddhcal.h
********************************************************************************
*/

#ifndef HEBRWCAL_H
#define HEBRWCAL_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/calendar.h"
#include "unicode/gregocal.h"

U_NAMESPACE_BEGIN

/**
 * <code>HebrewCalendar</code> is a subclass of <code>Calendar</code>
 * that that implements the traditional Hebrew calendar.
 * This is the civil calendar in Israel and the liturgical calendar
 * of the Jewish faith worldwide.
 * <p>
 * The Hebrew calendar is lunisolar and thus has a number of interesting
 * properties that distinguish it from the Gregorian.  Months start
 * on the day of (an arithmetic approximation of) each new moon.  Since the
 * solar year (approximately 365.24 days) is not an even multiple of
 * the lunar month (approximately 29.53 days) an extra "leap month" is
 * inserted in 7 out of every 19 years.  To make matters even more
 * interesting, the start of a year can be delayed by up to three days
 * in order to prevent certain holidays from falling on the Sabbath and
 * to prevent certain illegal year lengths.  Finally, the lengths of certain
 * months can vary depending on the number of days in the year.
 * <p>
 * The leap month is known as "Adar 1" and is inserted between the
 * months of Shevat and Adar in leap years.  Since the leap month does
 * not come at the end of the year, calculations involving
 * month numbers are particularly complex.  Users of this class should
 * make sure to use the {@link #roll roll} and {@link #add add} methods
 * rather than attempting to perform date arithmetic by manipulating
 * the fields directly.
 * <p>
 * <b>Note:</b> In the traditional Hebrew calendar, days start at sunset.
 * However, in order to keep the time fields in this class
 * synchronized with those of the other calendars and with local clock time,
 * we treat days and months as beginning at midnight,
 * roughly 6 hours after the corresponding sunset.
 * <p>
 * If you are interested in more information on the rules behind the Hebrew
 * calendar, see one of the following references:
 * <ul>
 * <li>"<a href="http://www.amazon.com/exec/obidos/ASIN/0521564743">Calendrical Calculations</a>",
 *      by Nachum Dershowitz & Edward Reingold, Cambridge University Press, 1997, pages 85-91.
 *
 * <li>Hebrew Calendar Science and Myths,
 *      <a href="http://www.geocities.com/Athens/1584/">
 *      http://www.geocities.com/Athens/1584/</a>
 *
 * <li>The Calendar FAQ,
 *      <a href="http://www.faqs.org/faqs/calendars/faq/">
 *      http://www.faqs.org/faqs/calendars/faq/</a>
 * </ul>
 * <p>
 * @see com.ibm.icu.util.GregorianCalendar
 *
 * @author Laura Werner
 * @author Alan Liu
 * @author Steven R. Loomis
 * <p>
 * @internal
 */
class U_I18N_API HebrewCalendar : public Calendar {
public:
  /**
   * Useful constants for HebrewCalendar.
   * @internal
   */
  enum EEras {
    /** 
     * Constant for Tishri, the 1st month of the Hebrew year. 
     */
      TISHRI,
      /**
     * Constant for Heshvan, the 2nd month of the Hebrew year. 
     */
      HESHVAN,
      /**
     * Constant for Kislev, the 3rd month of the Hebrew year. 
     */
      KISLEV,

    /**
     * Constant for Tevet, the 4th month of the Hebrew year. 
     */
      TEVET,

    /**
     * Constant for Shevat, the 5th month of the Hebrew year. 
     */
      SHEVAT,

    /**
     * Constant for Adar I, the 6th month of the Hebrew year
     * (present in leap years only). In non-leap years, the calendar
     * jumps from Shevat (5th month) to Adar (7th month).
     */
      ADAR_1,

    /** 
     * Constant for the Adar, the 7th month of the Hebrew year. 
     */
      ADAR,

    /**
     * Constant for Nisan, the 8th month of the Hebrew year. 
     */
      NISAN,

    /**
     * Constant for Iyar, the 9th month of the Hebrew year. 
     */
      IYAR,

    /**
     * Constant for Sivan, the 10th month of the Hebrew year. 
     */
      SIVAN,

    /**
     * Constant for Tammuz, the 11th month of the Hebrew year. 
     */
      TAMUZ,

    /**
     * Constant for Av, the 12th month of the Hebrew year. 
     */
      AV,

    /**
     * Constant for Elul, the 13th month of the Hebrew year. 
     */
      ELUL
    };

    /**
     * Constructs a HebrewCalendar based on the current time in the default time zone
     * with the given locale.
     *
     * @param aLocale  The given locale.
     * @param success  Indicates the status of HebrewCalendar object construction.
     *                 Returns U_ZERO_ERROR if constructed successfully.
     * @internal
     */
    HebrewCalendar(const Locale& aLocale, UErrorCode& success);


    /**
     * Destructor
     * @internal
     */
    virtual ~HebrewCalendar();

    /**
     * Copy constructor
     * @param source    the object to be copied.
     * @internal
     */
    HebrewCalendar(const HebrewCalendar& source);

    /**
     * Default assignment operator
     * @param right    the object to be copied.
     * @internal
     */
    HebrewCalendar& operator=(const HebrewCalendar& right);

    /**
     * Create and return a polymorphic copy of this calendar.
     * @return    return a polymorphic copy of this calendar.
     * @internal
     */
    virtual Calendar* clone(void) const;
    
public:
    /**
     * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual
     * override. This method is to implement a simple version of RTTI, since not all C++
     * compilers support genuine RTTI. Polymorphic operator==() and clone() methods call
     * this method.
     *
     * @return   The class ID for this object. All objects of a given class have the
     *           same class ID. Objects of other classes have different class IDs.
     * @internal
     */
    virtual UClassID getDynamicClassID(void) const;

    /**
     * Return the class ID for this class. This is useful only for comparing to a return
     * value from getDynamicClassID(). For example:
     *
     *      Base* polymorphic_pointer = createPolymorphicObject();
     *      if (polymorphic_pointer->getDynamicClassID() ==
     *          Derived::getStaticClassID()) ...
     *
     * @return   The class ID for all objects of this class.
     * @internal
     */
    static UClassID getStaticClassID(void);

    /**
     * return the calendar type, "hebrew".
     *
     * @return calendar type
     * @internal
     */
    virtual const char * getType() const;


    // Calendar API
 public:
    /**
     * (Overrides Calendar) UDate Arithmetic function. Adds the specified (signed) amount
     * of time to the given time field, based on the calendar's rules.  For more
     * information, see the documentation for Calendar::add().
     *
     * @param field   The time field.
     * @param amount  The amount of date or time to be added to the field.
     * @param status  Output param set to success/failure code on exit. If any value
     *                previously set in the time field is invalid, this will be set to
     *                an error status.
     */
    virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status);
    /**
     * @deprecated ICU 2.6 use UCalendarDateFields instead of EDateFields
     */
    inline virtual void add(EDateFields field, int32_t amount, UErrorCode& status) { add((UCalendarDateFields)field, amount, status); }


    /**
     * (Overrides Calendar) Rolls up or down by the given amount in the specified field.
     * For more information, see the documentation for Calendar::roll().
     *
     * @param field   The time field.
     * @param amount  Indicates amount to roll.
     * @param status  Output param set to success/failure code on exit. If any value
     *                previously set in the time field is invalid, this will be set to
     *                an error status.
     * @internal
     */
    virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode& status);

    /**
     * (Overrides Calendar) Rolls up or down by the given amount in the specified field.
     * For more information, see the documentation for Calendar::roll().
     *
     * @param field   The time field.
     * @param amount  Indicates amount to roll.
     * @param status  Output param set to success/failure code on exit. If any value
     *                previously set in the time field is invalid, this will be set to
     *                an error status.
     * @deprecated ICU 2.6. Use roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead.
`     */
    virtual void roll(EDateFields field, int32_t amount, UErrorCode& status);


 protected:

    /**
     * Subclass API for defining limits of different types.
     * Subclasses must implement this method to return limits for the
     * following fields:
     *
     * <pre>UCAL_ERA
     * UCAL_YEAR
     * UCAL_MONTH
     * UCAL_WEEK_OF_YEAR
     * UCAL_WEEK_OF_MONTH
     * UCAL_DATE (DAY_OF_MONTH on Java)
     * UCAL_DAY_OF_YEAR
     * UCAL_DAY_OF_WEEK_IN_MONTH
     * UCAL_YEAR_WOY
     * UCAL_EXTENDED_YEAR</pre>
     *
     * @param field one of the above field numbers
     * @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
     * <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
     * @internal
     */
    virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;

    /**
     * Return the number of days in the given month of the given extended
     * year of this calendar system.  Subclasses should override this
     * method if they can provide a more correct or more efficient
     * implementation than the default implementation in Calendar.
     * @internal
     */
    virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const;

    /**
     * Return the number of days in the given extended year of this
     * calendar system.  Subclasses should override this method if they can
     * provide a more correct or more efficient implementation than the
     * default implementation in Calendar.
     * @stable ICU 2.0
     */
    virtual int32_t handleGetYearLength(int32_t eyear) const;
    /**
     * Subclasses may override this method to compute several fields
     * specific to each calendar system.  These are:
     *
     * <ul><li>ERA
     * <li>YEAR
     * <li>MONTH
     * <li>DAY_OF_MONTH
     * <li>DAY_OF_YEAR
     * <li>EXTENDED_YEAR</ul>
     *
     * <p>The GregorianCalendar implementation implements
     * a calendar with the specified Julian/Gregorian cutover date.
     * @internal
     */
    virtual void handleComputeFields(int32_t julianDay, UErrorCode &status);
    /**
     * Return the extended year defined by the current fields.  This will
     * use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
     * as UCAL_ERA) specific to the calendar system, depending on which set of
     * fields is newer.
     * @return the extended year
     * @internal
     */
    virtual int32_t handleGetExtendedYear();
    /**
     * Return the Julian day number of day before the first day of the
     * given month in the given extended year.  Subclasses should override
     * this method to implement their calendar system.
     * @param eyear the extended year
     * @param month the zero-based month, or 0 if useMonth is false
     * @param useMonth if false, compute the day before the first day of
     * the given year, otherwise, compute the day before the first day of
     * the given month
     * @param return the Julian day number of the day before the first
     * day of the given month and year
     * @internal
     */
    virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month,
                                                   UBool useMonth) const;



 protected:

  /**
   * (Overrides Calendar) Return true if the current date for this Calendar is in
   * Daylight Savings Time. Recognizes DST_OFFSET, if it is set.
   *
   * @param status Fill-in parameter which receives the status of this operation.
   * @return   True if the current date for this Calendar is in Daylight Savings Time,
   *           false, otherwise.
   * @internal
   */
  virtual UBool inDaylightTime(UErrorCode& status) const;

    /**
     * Returns TRUE because the Hebrew Calendar does have a default century
     * @internal
     */
    virtual UBool haveDefaultCentury() const;

    /**
     * Returns the date of the start of the default century
     * @return start of century - in milliseconds since epoch, 1970
     * @internal
     */
    virtual UDate defaultCenturyStart() const;

    /**
     * Returns the year in which the default century begins
     * @internal
     */
    virtual int32_t defaultCenturyStartYear() const;

 private: // default century stuff.
    /**
     * The system maintains a static default century start date.  This is initialized
     * the first time it is used.  Before then, it is set to SYSTEM_DEFAULT_CENTURY to
     * indicate an uninitialized state.  Once the system default century date and year
     * are set, they do not change.
     */
    static UDate         fgSystemDefaultCenturyStart;

    /**
     * See documentation for systemDefaultCenturyStart.
     */
    static int32_t          fgSystemDefaultCenturyStartYear;

    /**
     * Default value that indicates the defaultCenturyStartYear is unitialized
     */
    static const int32_t    fgSystemDefaultCenturyYear;

    /**
     * start of default century, as a date
     */
    static const UDate        fgSystemDefaultCentury;

    /**
     * Returns the beginning date of the 100-year window that dates 
     * with 2-digit years are considered to fall within.
     */
    UDate         internalGetDefaultCenturyStart(void) const;

    /**
     * Returns the first year of the 100-year window that dates with 
     * 2-digit years are considered to fall within.
     */
    int32_t          internalGetDefaultCenturyStartYear(void) const;

    /**
     * Initializes the 100-year window that dates with 2-digit years
     * are considered to fall within so that its start date is 80 years
     * before the current time.
     */
    static void  initializeSystemDefaultCentury(void);

 private: // Calendar-specific implementation
    /**
     * Finds the day # of the first day in the given Hebrew year.
     * To do this, we want to calculate the time of the Tishri 1 new moon
     * in that year.
     * <p>
     * The algorithm here is similar to ones described in a number of
     * references, including:
     * <ul>
     * <li>"Calendrical Calculations", by Nachum Dershowitz & Edward Reingold,
     *     Cambridge University Press, 1997, pages 85-91.
     *
     * <li>Hebrew Calendar Science and Myths,
     *     <a href="http://www.geocities.com/Athens/1584/">
     *     http://www.geocities.com/Athens/1584/</a>
     *
     * <li>The Calendar FAQ,
     *      <a href="http://www.faqs.org/faqs/calendars/faq/">
     *      http://www.faqs.org/faqs/calendars/faq/</a>
     * </ul>
     * @param year extended year
     * @return day number (JD)
     * @internal
     */
    static int32_t startOfYear(int32_t year, UErrorCode& status);

    static int32_t absoluteDayToDayOfWeek(int32_t day) ;
    
    /**
     * @internal 
     */
    int32_t yearType(int32_t year) const;

    /**
     * @internal 
     */
    static UBool isLeapYear(int32_t year) ;
    /**
     * @internal 
     */
    static int32_t monthsInYear(int32_t year) ;
};

U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

#endif 
//eof


--- NEW FILE: i18n.vcproj.old ---
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="7.00"
	Name="i18n"
	SccProjectName=""
	SccLocalPath="">
	<Platforms>
		<Platform
			Name="Win32"/>
	</Platforms>
	<Configurations>
		<Configuration
			Name="Release|Win32"
			OutputDirectory=".\..\..\lib"
			IntermediateDirectory=".\Release"
			ConfigurationType="2"
			UseOfMFC="0"
			ATLMinimizesCRunTimeLibraryUsage="FALSE"
[...1141 lines suppressed...]
				<FileConfiguration
					Name="Release|Win32">
					<Tool
						Name="VCCustomBuildTool"
						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode"
						Outputs="..\..\include\unicode\$(InputFileName)"/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|Win32">
					<Tool
						Name="VCCustomBuildTool"
						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode"
						Outputs="..\..\include\unicode\$(InputFileName)"/>
				</FileConfiguration>
			</File>
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>

--- NEW FILE: islamcal.cpp ---
/*
 * Copyright (C) 2003, International Business Machines Corporation
 * and others. All Rights Reserved.
 ******************************************************************************
 *
 * File ISLAMCAL.H
 *
 * Modification History:
 *
 *   Date        Name        Description
 *   10/14/2003  srl         ported from java IslamicCalendar
 *****************************************************************************
 */

#include "islamcal.h"

#if !UCONFIG_NO_FORMATTING

#include "mutex.h"
#include <float.h>
#include "gregoimp.h" // Math
#include "astro.h" // CalendarAstronomer
#include "uhash.h"
#include "ucln_in.h"

static const UDate HIJRA_MILLIS = -42521587200000.0;    // 7/16/622 AD 00:00

// Debugging
#ifdef U_DEBUG_ISLAMCAL
# include <stdio.h>
# include <stdarg.h>
static void debug_islamcal_loc(const char *f, int32_t l)
{
  fprintf(stderr, "%s:%d: ", f, l);
}

static void debug_islamcal_msg(const char *pat, ...)
{
  va_list ap;
  va_start(ap, pat);
  vfprintf(stderr, pat, ap);
  fflush(stderr);
}
// must use double parens, i.e.:  U_DEBUG_ISLAMCAL_MSG(("four is: %d",4));
#define U_DEBUG_ISLAMCAL_MSG(x) {debug_islamcal_loc(__FILE__,__LINE__);debug_islamcal_msg x;}
#else
#define U_DEBUG_ISLAMCAL_MSG(x)
#endif


// --- The cache --
// cache of months
static UMTX astroLock = 0;  // pod bay door lock
static CalendarCache *gMonthCache = NULL;
static CalendarAstronomer *gIslamicCalendarAstro = NULL;

U_NAMESPACE_BEGIN

// Implementation of the IslamicCalendar class

//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------

const char *IslamicCalendar::getType() const { 
  if(civil==CIVIL) {
    return "islamic-civil";
  } else {
    return "islamic";
  }
}

Calendar* IslamicCalendar::clone() const {
  return new IslamicCalendar(*this);
}

IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success, ECivil beCivil)
  :   Calendar(TimeZone::createDefault(), aLocale, success),
      civil(beCivil)
{
  setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
}

IslamicCalendar::IslamicCalendar(const IslamicCalendar& other) : Calendar(other), civil(other.civil) {
}

IslamicCalendar::~IslamicCalendar()
{
}

/**
 * Determines whether this object uses the fixed-cycle Islamic civil calendar
 * or an approximation of the religious, astronomical calendar.
 *
 * @param beCivil   <code>true</code> to use the civil calendar,
 *                  <code>false</code> to use the astronomical calendar.
 * @draft ICU 2.4
 */
void IslamicCalendar::setCivil(ECivil beCivil, UErrorCode &status)
{
  if (civil != beCivil) {
    // The fields of the calendar will become invalid, because the calendar
    // rules are different
    UDate m = getTimeInMillis(status);
    civil = beCivil;
    clear();
    setTimeInMillis(m, status);
  }
}
    
/**
 * Returns <code>true</code> if this object is using the fixed-cycle civil
 * calendar, or <code>false</code> if using the religious, astronomical
 * calendar.
 * @draft ICU 2.4
 */
UBool IslamicCalendar::isCivil() {
  return (civil == CIVIL);
}
    
//-------------------------------------------------------------------------
// Minimum / Maximum access functions
//-------------------------------------------------------------------------

static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = {
  // Minimum  Greatest    Least  Maximum
  //           Minimum  Maximum
  {        0,        0,       0,       0 }, // ERA
  {        1,        1, 5000000, 5000000 }, // YEAR
  {        0,        0,      11,      11 }, // MONTH
  {        1,        1,      51,      52 }, // WEEK_OF_YEAR
  {        0,        0,       5,       6 }, // WEEK_OF_MONTH
  {        1,        1,      29,      30 }, // DAY_OF_MONTH
  {        1,        1,     354,     355 }, // DAY_OF_YEAR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
  {       -1,       -1,       4,       5 }, // DAY_OF_WEEK_IN_MONTH
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
  { 1, 1, 5000001, 5000001 }, // YEAR_WOY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
  { 1, 1, 5000000, 5000000 }, // EXTENDED_YEAR
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1} // MILLISECONDS_IN_DAY
};

/**
 * @draft ICU 2.4
 */
int32_t IslamicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
  return LIMITS[field][limitType];
}

//-------------------------------------------------------------------------
// Assorted calculation utilities
//

/**
 * Determine whether a year is a leap year in the Islamic civil calendar
 */
UBool IslamicCalendar::civilLeapYear(int32_t year)
{
  return (14 + 11 * year) % 30 < 11;
}
    
/**
 * Return the day # on which the given year starts.  Days are counted
 * from the Hijri epoch, origin 0.
 */
int32_t IslamicCalendar::yearStart(int32_t year) {
  if (civil == CIVIL) {
    return (year-1)*354 + Math::floorDivide((3+11*year),30);
  } else {
    return trueMonthStart(12*(year-1));
  }
}
    
/**
 * Return the day # on which the given month starts.  Days are counted
 * from the Hijri epoch, origin 0.
 *
 * @param year  The hijri year
 * @param year  The hijri month, 0-based
 */
int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const {
  if (civil == CIVIL) {
    return (int32_t)uprv_ceil(29.5*month)
      + (year-1)*354 + (int32_t)Math::floorDivide((3+11*year),30);
  } else {
    return trueMonthStart(12*(year-1) + month);
  }
}
    
/**
 * Find the day number on which a particular month of the true/lunar
 * Islamic calendar starts.
 *
 * @param month The month in question, origin 0 from the Hijri epoch
 *
 * @return The day number on which the given month starts.
 */
int32_t IslamicCalendar::trueMonthStart(int32_t month) const
{
  UErrorCode status = U_ZERO_ERROR;
  int32_t start = CalendarCache::get(&gMonthCache, month, status);
  
  if (start==0) {
    // Make a guess at when the month started, using the average length
    UDate origin = HIJRA_MILLIS 
      + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH - 1) * kOneDay;
    
    double age = moonAge(origin);
    
    if (moonAge(origin) >= 0) {
      // The month has already started
      do {
        origin -= kOneDay;
        age = moonAge(origin);
      } while (age >= 0);
    }
    else {
      // Preceding month has not ended yet.
      do {
          origin += kOneDay;
        age = moonAge(origin);
      } while (age < 0);
    }
    start = (int32_t)Math::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1;
    CalendarCache::put(&gMonthCache, month, start, status);
  }
  if(U_FAILURE(status)) {
    start = 0;
  }
  return start;
}

/**
 * Return the "age" of the moon at the given time; this is the difference
 * in ecliptic latitude between the moon and the sun.  This method simply
 * calls CalendarAstronomer.moonAge, converts to degrees, 
 * and adjusts the result to be in the range [-180, 180].
 *
 * @param time  The time at which the moon's age is desired,
 *              in millis since 1/1/1970.
 */
double IslamicCalendar::moonAge(UDate time)
{
  double age = 0;

  umtx_lock(&astroLock);
  if(gIslamicCalendarAstro == NULL) {
    gIslamicCalendarAstro = new CalendarAstronomer();
  }
  gIslamicCalendarAstro->setTime(time);
  age = gIslamicCalendarAstro->getMoonAge();
  ucln_i18n_registerCleanup();
  umtx_unlock(&astroLock);

  // Convert to degrees and normalize...
  age = age * 180 / CalendarAstronomer::PI;
  if (age > 180) {
    age = age - 360;
  }

  return age;
}

//----------------------------------------------------------------------
// Calendar framework
//----------------------------------------------------------------------

/**
 * Return the length (in days) of the given month.
 *
 * @param year  The hijri year
 * @param year  The hijri month, 0-based
 * @draft ICU 2.4
 */
int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {

  int32_t length = 0;
        
  if (civil == CIVIL) {
    length = 29 + (month+1) % 2;
    if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
      length++;
    }
  } else {
    month = 12*(extendedYear-1) + month;
    length =  trueMonthStart(month+1) - trueMonthStart(month) ;
  }
  return length;
}

/**
 * Return the number of days in the given Islamic year
 * @draft ICU 2.4
 */
int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const {
  if (civil == CIVIL) {
    return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
  } else {
    int32_t month = 12*(extendedYear-1);
    return (trueMonthStart(month + 12) - trueMonthStart(month));
  }
}
    
//-------------------------------------------------------------------------
// Functions for converting from field values to milliseconds....
//-------------------------------------------------------------------------

// Return JD of start of given month/year
/**
 * @draft ICU 2.4
 */
int32_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */) const {
  return monthStart(eyear, month) + 1948439;
}    

//-------------------------------------------------------------------------
// Functions for converting from milliseconds to field values
//-------------------------------------------------------------------------

    /**
     * @draft ICU 2.4
     */
int32_t IslamicCalendar::handleGetExtendedYear() {
    int32_t year;
    if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
        year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
    } else {
        year = internalGet(UCAL_YEAR, 1); // Default to year 1
    }
    return year;
}

/**
 * Override Calendar to compute several fields specific to the Islamic
 * calendar system.  These are:
 *
 * <ul><li>ERA
 * <li>YEAR
 * <li>MONTH
 * <li>DAY_OF_MONTH
 * <li>DAY_OF_YEAR
 * <li>EXTENDED_YEAR</ul>
 * 
 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
 * method is called. The getGregorianXxx() methods return Gregorian
 * calendar equivalents for the given Julian day.
     * @draft ICU 2.4
     */
void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/) {
    int32_t year, month, dayOfMonth, dayOfYear;
    UDate startDate;
    int32_t days = julianDay - 1948440;
    
    if (civil == CIVIL) {
        // Use the civil calendar approximation, which is just arithmetic
        year  = (int)Math::floorDivide( (double)(30 * days + 10646) , 10631.0 );
        month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 );
        month = month<11?month:11;
        startDate = monthStart(year, month);
    } else {
        // Guess at the number of elapsed full months since the epoch
        int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH);

        startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH - 1);

        if ( days - startDate >= 28 && moonAge(internalGetTime()) > 0) {
            // If we're near the end of the month, assume next month and search backwards
            months++;
        }

        // Find out the last time that the new moon was actually visible at this longitude
        // This returns midnight the night that the moon was visible at sunset.
        while ((startDate = trueMonthStart(months)) > days) {
            // If it was after the date in question, back up a month and try again
            months--;
        }
        
        year = months / 12 + 1;
        month = months % 12;
    }
    
    dayOfMonth = (days - monthStart(year, month)) + 1;

    // Now figure out the day of the year.
    dayOfYear = (days - monthStart(year, 0) + 1);

    internalSet(UCAL_ERA, 0);
    internalSet(UCAL_YEAR, year);
    internalSet(UCAL_EXTENDED_YEAR, year);
    internalSet(UCAL_MONTH, month);
    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);       
}    

UBool
IslamicCalendar::inDaylightTime(UErrorCode& status) const
{
// copied from GregorianCalendar
if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) 
  return FALSE;

    // Force an update of the state of the Calendar.
((IslamicCalendar*)this)->complete(status); // cast away const

return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
}

// default century
const UDate     IslamicCalendar::fgSystemDefaultCentury        = DBL_MIN;
const int32_t   IslamicCalendar::fgSystemDefaultCenturyYear    = -1;

UDate           IslamicCalendar::fgSystemDefaultCenturyStart       = DBL_MIN;
int32_t         IslamicCalendar::fgSystemDefaultCenturyStartYear   = -1;


UBool IslamicCalendar::haveDefaultCentury() const
{
  return TRUE;
}

UDate IslamicCalendar::defaultCenturyStart() const
{
  return internalGetDefaultCenturyStart();
}

int32_t IslamicCalendar::defaultCenturyStartYear() const
{
  return internalGetDefaultCenturyStartYear();
}

UDate
IslamicCalendar::internalGetDefaultCenturyStart() const
{
  // lazy-evaluate systemDefaultCenturyStart
  UBool needsUpdate;
  { 
    Mutex m;
    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
  }

  if (needsUpdate) {
    initializeSystemDefaultCentury();
  }

  // use defaultCenturyStart unless it's the flag value;
  // then use systemDefaultCenturyStart
  
  return fgSystemDefaultCenturyStart;
}

int32_t
IslamicCalendar::internalGetDefaultCenturyStartYear() const
{
  // lazy-evaluate systemDefaultCenturyStartYear
  UBool needsUpdate;
  { 
    Mutex m;
    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
  }

  if (needsUpdate) {
    initializeSystemDefaultCentury();
  }

  // use defaultCenturyStart unless it's the flag value;
  // then use systemDefaultCenturyStartYear
  
  return    fgSystemDefaultCenturyStartYear;
}

void
IslamicCalendar::initializeSystemDefaultCentury()
{
  // initialize systemDefaultCentury and systemDefaultCenturyYear based
  // on the current time.  They'll be set to 80 years before
  // the current time.
  // No point in locking as it should be idempotent.
  if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
  {
    UErrorCode status = U_ZERO_ERROR;
    Calendar *calendar = new IslamicCalendar(Locale("ar@calendar=islamic-civil"),status);
    if (calendar != NULL && U_SUCCESS(status))
    {
      calendar->setTime(Calendar::getNow(), status);
      calendar->add(UCAL_YEAR, -80, status);
      UDate    newStart =  calendar->getTime(status);
      int32_t  newYear  =  calendar->get(UCAL_YEAR, status);
      {
        Mutex m;
        fgSystemDefaultCenturyStart = newStart;
        fgSystemDefaultCenturyStartYear = newYear;
      }
      delete calendar;
    }
    // We have no recourse upon failure unless we want to propagate the failure
    // out.
  }
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)


U_NAMESPACE_END

U_CFUNC UBool calendar_islamic_cleanup(void) {
    if (gMonthCache) {
        delete gMonthCache;
        gMonthCache = NULL;
    }
    if (gIslamicCalendarAstro) {
        delete gIslamicCalendarAstro;
        gIslamicCalendarAstro = NULL;
    }
    umtx_destroy(&astroLock);
    return TRUE;
}

#endif


--- NEW FILE: islamcal.h ---
/*
 * Copyright (C) 2003, International Business Machines Corporation
 * and others. All Rights Reserved.
 ******************************************************************************
 *
 * File ISLAMCAL.H
 *
 * Modification History:
 *
 *   Date        Name        Description
 *   10/14/2003  srl         ported from java IslamicCalendar
 *****************************************************************************
 */

#ifndef ISLAMCAL_H
#define ISLAMCAL_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/calendar.h"

U_NAMESPACE_BEGIN

/**
 * <code>IslamicCalendar</code> is a subclass of <code>Calendar</code>
 * that that implements the Islamic civil and religious calendars.  It
 * is used as the civil calendar in most of the Arab world and the
 * liturgical calendar of the Islamic faith worldwide.  This calendar
 * is also known as the "Hijri" calendar, since it starts at the time
 * of Mohammed's emigration (or "hijra") to Medinah on Thursday, 
 * July 15, 622 AD (Julian).
 * <p>
 * The Islamic calendar is strictly lunar, and thus an Islamic year of twelve
 * lunar months does not correspond to the solar year used by most other
 * calendar systems, including the Gregorian.  An Islamic year is, on average,
 * about 354 days long, so each successive Islamic year starts about 11 days
 * earlier in the corresponding Gregorian year.
 * <p>
 * Each month of the calendar starts when the new moon's crescent is visible
 * at sunset.  However, in order to keep the time fields in this class
 * synchronized with those of the other calendars and with local clock time,
 * we treat days and months as beginning at midnight,
 * roughly 6 hours after the corresponding sunset.
 * <p>
 * There are two main variants of the Islamic calendar in existence.  The first
 * is the <em>civil</em> calendar, which uses a fixed cycle of alternating 29-
 * and 30-day months, with a leap day added to the last month of 11 out of
 * every 30 years.  This calendar is easily calculated and thus predictable in
 * advance, so it is used as the civil calendar in a number of Arab countries.
 * This is the default behavior of a newly-created <code>IslamicCalendar</code>
 * object.
 * <p>
 * The Islamic <em>religious</em> calendar, however, is based on the <em>observation</em>
 * of the crescent moon.  It is thus affected by the position at which the
 * observations are made, seasonal variations in the time of sunset, the
 * eccentricities of the moon's orbit, and even the weather at the observation
 * site.  This makes it impossible to calculate in advance, and it causes the
 * start of a month in the religious calendar to differ from the civil calendar
 * by up to three days.
 * <p>
 * Using astronomical calculations for the position of the sun and moon, the
 * moon's illumination, and other factors, it is possible to determine the start
 * of a lunar month with a fairly high degree of certainty.  However, these
 * calculations are extremely complicated and thus slow, so most algorithms,
 * including the one used here, are only approximations of the true astronical
 * calculations.  At present, the approximations used in this class are fairly
 * simplistic; they will be improved in later versions of the code.
 * <p>
 * The {@link #setCivil setCivil} method determines
 * which approach is used to determine the start of a month.  By default, the
 * fixed-cycle civil calendar is used.  However, if <code>setCivil(false)</code>
 * is called, an approximation of the true lunar calendar will be used.
 *
 * @see GregorianCalendar
 *
 * @author Laura Werner
 * @author Alan Liu
 * @author Steven R. Loomis
 * @internal
 */
class U_I18N_API IslamicCalendar : public Calendar {
 public:
  //-------------------------------------------------------------------------
  // Constants...
  //-------------------------------------------------------------------------
  /**
   * Calendar type - civil or religious
   * @internal 
   */
  enum ECivil {
    ASTRONOMICAL,
    CIVIL
  };
  
  /**
   * Constants for the months
   * @internal
   */
  enum EMonths {
    /**
     * Constant for Muharram, the 1st month of the Islamic year. 
     * @internal
     */
    MUHARRAM = 0,

    /**
     * Constant for Safar, the 2nd month of the Islamic year. 
     * @internal
     */
    SAFAR = 1,

    /**
     * Constant for Rabi' al-awwal (or Rabi' I), the 3rd month of the Islamic year. 
     * @internal 
     */
    RABI_1 = 2,

    /**
     * Constant for Rabi' al-thani or (Rabi' II), the 4th month of the Islamic year. 
     * @internal 
     */
    RABI_2 = 3,

    /**
     * Constant for Jumada al-awwal or (Jumada I), the 5th month of the Islamic year. 
     * @internal 
     */
    JUMADA_1 = 4,

    /**
     * Constant for Jumada al-thani or (Jumada II), the 6th month of the Islamic year. 
     * @internal 
     */
    JUMADA_2 = 5,

    /**
     * Constant for Rajab, the 7th month of the Islamic year. 
     * @internal 
     */
    RAJAB = 6,

    /**
     * Constant for Sha'ban, the 8th month of the Islamic year. 
     * @internal 
     */
    SHABAN = 7,

    /**
     * Constant for Ramadan, the 9th month of the Islamic year. 
     * @internal 
     */
    RAMADAN = 8,

    /**
     * Constant for Shawwal, the 10th month of the Islamic year. 
     * @internal 
     */
    SHAWWAL = 9,

    /**
     * Constant for Dhu al-Qi'dah, the 11th month of the Islamic year. 
     * @internal 
     */
    DHU_AL_QIDAH = 10,

    /**
     * Constant for Dhu al-Hijjah, the 12th month of the Islamic year. 
     * @internal 
     */
    DHU_AL_HIJJAH = 11,
    
    ISLAMIC_MONTH_MAX
  }; 



  //-------------------------------------------------------------------------
  // Constructors...
  //-------------------------------------------------------------------------

  /**
   * Constructs an IslamicCalendar based on the current time in the default time zone
   * with the given locale.
   *
   * @param aLocale  The given locale.
   * @param success  Indicates the status of IslamicCalendar object construction.
   *                 Returns U_ZERO_ERROR if constructed successfully.
   * @param beCivil  Whether the calendar should be civil (default-TRUE) or religious (FALSE)
   * @internal
   */
  IslamicCalendar(const Locale& aLocale, UErrorCode &success, ECivil beCivil = CIVIL);

  /**
   * Copy Constructor
   * @internal
   */
  IslamicCalendar(const IslamicCalendar& other);

  /**
   * Destructor.
   * @internal
   */
  virtual ~IslamicCalendar();

  /**
   * Determines whether this object uses the fixed-cycle Islamic civil calendar
   * or an approximation of the religious, astronomical calendar.
   *
   * @param beCivil   <code>CIVIL</code> to use the civil calendar,
   *                  <code>ASTRONOMICAL</code> to use the astronomical calendar.
   * @internal
   */
  void setCivil(ECivil beCivil, UErrorCode &status);
    
  /**
   * Returns <code>true</code> if this object is using the fixed-cycle civil
   * calendar, or <code>false</code> if using the religious, astronomical
   * calendar.
   * @internal
   */
  UBool isCivil();


  // TODO: copy c'tor, etc

  // clone
  virtual Calendar* clone() const;

 private:
  /**
   * Determine whether a year is a leap year in the Islamic civil calendar
   */
  static UBool civilLeapYear(int32_t year);
    
  /**
   * Return the day # on which the given year starts.  Days are counted
   * from the Hijri epoch, origin 0.
   */
  int32_t yearStart(int32_t year);

  /**
   * Return the day # on which the given month starts.  Days are counted
   * from the Hijri epoch, origin 0.
   *
   * @param year  The hijri year
   * @param year  The hijri month, 0-based
   */
  int32_t monthStart(int32_t year, int32_t month) const;
    
  /**
   * Find the day number on which a particular month of the true/lunar
   * Islamic calendar starts.
   *
   * @param month The month in question, origin 0 from the Hijri epoch
   *
   * @return The day number on which the given month starts.
   */
  int32_t trueMonthStart(int32_t month) const;

  /**
   * Return the "age" of the moon at the given time; this is the difference
   * in ecliptic latitude between the moon and the sun.  This method simply
   * calls CalendarAstronomer.moonAge, converts to degrees, 
   * and adjusts the resultto be in the range [-180, 180].
   *
   * @param time  The time at which the moon's age is desired,
   *              in millis since 1/1/1970.
   */
  static double moonAge(UDate time);

  //-------------------------------------------------------------------------
  // Internal data....
  //
    
  /**
   * <code>CIVIL</code> if this object uses the fixed-cycle Islamic civil calendar,
   * and <code>ASTRONOMICAL</code> if it approximates the true religious calendar using
   * astronomical calculations for the time of the new moon.
   */
  ECivil civil;

  //----------------------------------------------------------------------
  // Calendar framework
  //----------------------------------------------------------------------
 protected:
  /**
   * @internal
   */
  virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
  
  /**
   * Return the length (in days) of the given month.
   *
   * @param year  The hijri year
   * @param year  The hijri month, 0-based
   * @internal
   */
  virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const;
  
  /**
   * Return the number of days in the given Islamic year
   * @internal
   */
  virtual int32_t handleGetYearLength(int32_t extendedYear) const;
    
  //-------------------------------------------------------------------------
  // Functions for converting from field values to milliseconds....
  //-------------------------------------------------------------------------

  // Return JD of start of given month/year
  /**
   * @internal
   */
  virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const;

  //-------------------------------------------------------------------------
  // Functions for converting from milliseconds to field values
  //-------------------------------------------------------------------------

  /**
   * @internal
   */
  virtual int32_t handleGetExtendedYear();

  /**
   * Override Calendar to compute several fields specific to the Islamic
   * calendar system.  These are:
   *
   * <ul><li>ERA
   * <li>YEAR
   * <li>MONTH
   * <li>DAY_OF_MONTH
   * <li>DAY_OF_YEAR
   * <li>EXTENDED_YEAR</ul>
   * 
   * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
   * method is called. The getGregorianXxx() methods return Gregorian
   * calendar equivalents for the given Julian day.
   * @internal
   */
  virtual void handleComputeFields(int32_t julianDay, UErrorCode &status);

  // UObject stuff
 public: 
  /**
   * @return   The class ID for this object. All objects of a given class have the
   *           same class ID. Objects of other classes have different class IDs.
   * @internal
   */
  virtual UClassID getDynamicClassID(void) const;

  /**
   * Return the class ID for this class. This is useful only for comparing to a return
   * value from getDynamicClassID(). For example:
   *
   *      Base* polymorphic_pointer = createPolymorphicObject();
   *      if (polymorphic_pointer->getDynamicClassID() ==
   *          Derived::getStaticClassID()) ...
   *
   * @return   The class ID for all objects of this class.
   * @internal
   */
  static UClassID getStaticClassID(void);

  /**
   * return the calendar type, "buddhist".
   *
   * @return calendar type
   * @internal
   */
  virtual const char * getType() const;

 private:
  IslamicCalendar(); // default constructor not implemented

  // Default century.
 protected:

  /**
   * (Overrides Calendar) Return true if the current date for this Calendar is in
   * Daylight Savings Time. Recognizes DST_OFFSET, if it is set.
   *
   * @param status Fill-in parameter which receives the status of this operation.
   * @return   True if the current date for this Calendar is in Daylight Savings Time,
   *           false, otherwise.
   * @internal
   */
  virtual UBool inDaylightTime(UErrorCode& status) const;


  /**
   * Returns TRUE because the Islamic Calendar does have a default century
   * @internal
   */
  virtual UBool haveDefaultCentury() const;

  /**
   * Returns the date of the start of the default century
   * @return start of century - in milliseconds since epoch, 1970
   * @internal
   */
  virtual UDate defaultCenturyStart() const;

  /**
   * Returns the year in which the default century begins
   * @internal
   */
  virtual int32_t defaultCenturyStartYear() const;

 private: // default century stuff.
  /**
   * The system maintains a static default century start date.  This is initialized
   * the first time it is used.  Before then, it is set to SYSTEM_DEFAULT_CENTURY to
   * indicate an uninitialized state.  Once the system default century date and year
   * are set, they do not change.
   */
  static UDate         fgSystemDefaultCenturyStart;

  /**
   * See documentation for systemDefaultCenturyStart.
   */
  static int32_t          fgSystemDefaultCenturyStartYear;

  /**
   * Default value that indicates the defaultCenturyStartYear is unitialized
   */
  static const int32_t    fgSystemDefaultCenturyYear;

  /**
   * start of default century, as a date
   */
  static const UDate        fgSystemDefaultCentury;

  /**
   * Returns the beginning date of the 100-year window that dates 
   * with 2-digit years are considered to fall within.
   */
  UDate         internalGetDefaultCenturyStart(void) const;

  /**
   * Returns the first year of the 100-year window that dates with 
   * 2-digit years are considered to fall within.
   */
  int32_t          internalGetDefaultCenturyStartYear(void) const;

  /**
   * Initializes the 100-year window that dates with 2-digit years
   * are considered to fall within so that its start date is 80 years
   * before the current time.
   */
  static void  initializeSystemDefaultCentury(void);
};

U_NAMESPACE_END

#endif
#endif




--- NEW FILE: olsontz.cpp ---
/*
**********************************************************************
* Copyright (c) 2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: July 21 2003
* Since: ICU 2.8
**********************************************************************
*/

#include "olsontz.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/ures.h"
#include "unicode/simpletz.h"
#include "unicode/gregocal.h"
#include "gregoimp.h"
#include "cmemory.h"
#include "uassert.h"
#include <float.h> // DBL_MAX

#ifdef U_DEBUG_TZ
# include <stdio.h>
# include "uresimp.h" // for debugging

static void debug_tz_loc(const char *f, int32_t l)
{
  fprintf(stderr, "%s:%d: ", f, l);
}

static void debug_tz_msg(const char *pat, ...)
{
  va_list ap;
  va_start(ap, pat);
  vfprintf(stderr, pat, ap);
  fflush(stderr);
}
// must use double parens, i.e.:  U_DEBUG_TZ_MSG(("four is: %d",4));
#define U_DEBUG_TZ_MSG(x) {debug_tz_loc(__FILE__,__LINE__);debug_tz_msg x;}
#else
#define U_DEBUG_TZ_MSG(x)
#endif

U_NAMESPACE_BEGIN

#define SECONDS_PER_DAY (24*60*60)

static const int32_t ZEROS[] = {0,0};

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OlsonTimeZone)

/**
 * Default constructor.  Creates a time zone with an empty ID and
 * a fixed GMT offset of zero.
 */
OlsonTimeZone::OlsonTimeZone() : finalYear(INT32_MAX), finalMillis(DBL_MAX), finalZone(0) {
    constructEmpty();
}

/**
 * Construct a GMT+0 zone with no transitions.  This is done when a
 * constructor fails so the resultant object is well-behaved.
 */
void OlsonTimeZone::constructEmpty() {
    transitionCount = 0;
    typeCount = 1;
    transitionTimes = typeOffsets = ZEROS;
    typeData = (const uint8_t*) ZEROS;
}

/**
 * Construct from a resource bundle
 * @param top the top-level zoneinfo resource bundle.  This is used
 * to lookup the rule that `res' may refer to, if there is one.
 * @param res the resource bundle of the zone to be constructed
 * @param ec input-output error code
 */
OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top,
                             const UResourceBundle* res,
                             UErrorCode& ec) :
  finalYear(INT32_MAX), finalMillis(DBL_MAX), finalZone(0)
{
    U_DEBUG_TZ_MSG(("OlsonTimeZone(%s)\n", ures_getKey((UResourceBundle*)res)));
    if ((top == NULL || res == NULL) && U_SUCCESS(ec)) {
        ec = U_ILLEGAL_ARGUMENT_ERROR;
    }
    if (U_SUCCESS(ec)) {
        // TODO -- clean up -- Doesn't work if res points to an alias
        //        // TODO remove nonconst casts below when ures_* API is fixed
        //        setID(ures_getKey((UResourceBundle*) res)); // cast away const

        // Size 1 is an alias TO another zone (int)
        // HOWEVER, the caller should dereference this and never pass it in to us
        // Size 3 is a purely historical zone (no final rules)
        // Size 4 is like size 3, but with an alias list at the end
        // Size 5 is a hybrid zone, with historical and final elements
        // Size 6 is like size 5, but with an alias list at the end
        int32_t size = ures_getSize((UResourceBundle*) res); // cast away const
        if (size < 3 || size > 6) {
            ec = U_INVALID_FORMAT_ERROR;
        }

        // Transitions list may be empty
        int32_t i;
        UResourceBundle* r = ures_getByIndex(res, 0, NULL, &ec);
        transitionTimes = ures_getIntVector(r, &i, &ec);
        ures_close(r);
        if ((i<0 || i>0x7FFF) && U_SUCCESS(ec)) {
            ec = U_INVALID_FORMAT_ERROR;
        }
        transitionCount = (int16_t) i;
        
        // Type offsets list must be of even size, with size >= 2
        r = ures_getByIndex(res, 1, NULL, &ec);
        typeOffsets = ures_getIntVector(r, &i, &ec);
        ures_close(r);
        if ((i<2 || i>0x7FFE || ((i&1)!=0)) && U_SUCCESS(ec)) {
            ec = U_INVALID_FORMAT_ERROR;
        }
        typeCount = (int16_t) i >> 1;

        // Type data must be of the same size as the transitions list        
        r = ures_getByIndex(res, 2, NULL, &ec);
        int32_t len;
        typeData = ures_getBinary(r, &len, &ec);
        ures_close(r);
        if (len != transitionCount && U_SUCCESS(ec)) {
            ec = U_INVALID_FORMAT_ERROR;
        }

#if defined (U_DEBUG_TZ)
        U_DEBUG_TZ_MSG(("OlsonTimeZone(%s) - size = %d, typecount %d transitioncount %d - err %s\n", ures_getKey((UResourceBundle*)res), size, typeCount,  transitionCount, u_errorName(ec)));
        if(U_SUCCESS(ec)) {
          int32_t jj;
          for(jj=0;jj<transitionCount;jj++) {
            U_DEBUG_TZ_MSG(("   Transition %d:  time %d, typedata%d\n", jj, transitionTimes[jj], typeData[jj]));
          }
          for(jj=0;jj<transitionCount;jj++) {
            U_DEBUG_TZ_MSG(("   Type %d:  offset%d\n", jj, typeOffsets[jj]));
          }
        }
#endif

        // Process final rule and data, if any
        if (size >= 5) {
            int32_t ruleidLen = 0;
            const UChar* idUStr = ures_getStringByIndex(res, 3, &ruleidLen, &ec);
            UnicodeString ruleid(TRUE, idUStr, ruleidLen);
            r = ures_getByIndex(res, 4, NULL, &ec);
            const int32_t* data = ures_getIntVector(r, &len, &ec);
#if defined U_DEBUG_TZ
            const char *rKey = ures_getKey(r);
            const char *zKey = ures_getKey((UResourceBundle*)res);
#endif
            ures_close(r);
            if (U_SUCCESS(ec)) {
                if (data != 0 && len == 2) {
                    int32_t rawOffset = data[0] * U_MILLIS_PER_SECOND;
                    // Subtract one from the actual final year; we
                    // actually store final year - 1, and compare
                    // using > rather than >=.  This allows us to use
                    // INT32_MAX as an exclusive upper limit for all
                    // years, including INT32_MAX.
                    U_ASSERT(data[1] > INT32_MIN);
                    finalYear = data[1] - 1;
                    // Also compute the millis for Jan 1, 0:00 GMT of the
                    // finalYear.  This reduces runtime computations.
                    finalMillis = Grego::fieldsToDay(data[1], 0, 1) * U_MILLIS_PER_DAY;
                    U_DEBUG_TZ_MSG(("zone%s|%s: {%d,%d}, finalYear%d, finalMillis%.1lf\n",
                                    zKey,rKey, data[0], data[1], finalYear, finalMillis));
                    r = TimeZone::loadRule(top, ruleid, NULL, ec);
                    if (U_SUCCESS(ec)) {
                        // 3, 1, -1, 7200, 0, 9, -31, -1, 7200, 0, 3600
                        data = ures_getIntVector(r, &len, &ec);
                        if (U_SUCCESS(ec) && len == 11) {
                            U_DEBUG_TZ_MSG(("zone%s, rule%s: {%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}", zKey, ures_getKey(r), 
                                          data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10]));
                            finalZone = new SimpleTimeZone(rawOffset, "",
                                (int8_t)data[0], (int8_t)data[1], (int8_t)data[2],
                                data[3] * U_MILLIS_PER_SECOND,
                                (SimpleTimeZone::TimeMode) data[4],
                                (int8_t)data[5], (int8_t)data[6], (int8_t)data[7],
                                data[8] * U_MILLIS_PER_SECOND,
                                (SimpleTimeZone::TimeMode) data[9],
                                data[10] * U_MILLIS_PER_SECOND, ec);
                        } else {
                            ec = U_INVALID_FORMAT_ERROR;
                        }
                    }
                    ures_close(r);
                } else {
                    ec = U_INVALID_FORMAT_ERROR;
                }
            }
        }
    }

    if (U_FAILURE(ec)) {
        constructEmpty();
    }
}

/**
 * Copy constructor
 */
OlsonTimeZone::OlsonTimeZone(const OlsonTimeZone& other) :
    TimeZone(other), finalZone(0) {
    *this = other;
}

/**
 * Assignment operator
 */
OlsonTimeZone& OlsonTimeZone::operator=(const OlsonTimeZone& other) {
    transitionCount = other.transitionCount;
    typeCount = other.typeCount;
    transitionTimes = other.transitionTimes;
    typeOffsets = other.typeOffsets;
    typeData = other.typeData;
    finalYear = other.finalYear;
    finalMillis = other.finalMillis;
    delete finalZone;
    finalZone = (other.finalZone != 0) ?
        (SimpleTimeZone*) other.finalZone->clone() : 0;
    return *this;
}

/**
 * Destructor
 */
OlsonTimeZone::~OlsonTimeZone() {
    delete finalZone;
}

/**
 * Returns true if the two TimeZone objects are equal.
 */
UBool OlsonTimeZone::operator==(const TimeZone& other) const {
    const OlsonTimeZone* z = (const OlsonTimeZone*) &other;

    return TimeZone::operator==(other) &&
        // [sic] pointer comparison: typeData points into
        // memory-mapped or DLL space, so if two zones have the same
        // pointer, they are equal.
        (typeData == z->typeData ||
         // If the pointers are not equal, the zones may still
         // be equal if their rules and transitions are equal
         (finalYear == z->finalYear &&
          // Don't compare finalMillis; if finalYear is ==, so is finalMillis
          ((finalZone == 0 && z->finalZone == 0) ||
           (finalZone != 0 && z->finalZone != 0 &&
            *finalZone == *z->finalZone)) &&
          transitionCount == z->transitionCount &&
          typeCount == z->typeCount &&
          uprv_memcmp(transitionTimes, z->transitionTimes,
                      sizeof(transitionTimes[0]) * transitionCount) == 0 &&
          uprv_memcmp(typeOffsets, z->typeOffsets,
                      (sizeof(typeOffsets[0]) * typeCount) << 1) == 0 &&
          uprv_memcmp(typeData, z->typeData,
                      (sizeof(typeData[0]) * typeCount)) == 0
          ));
}

/**
 * TimeZone API.
 */
TimeZone* OlsonTimeZone::clone() const {
    return new OlsonTimeZone(*this);
}

/**
 * TimeZone API.
 */
int32_t OlsonTimeZone::getOffset(uint8_t era, int32_t year, int32_t month,
                                 int32_t dom, uint8_t dow,
                                 int32_t millis, UErrorCode& ec) const {
    if (month < UCAL_JANUARY || month > UCAL_DECEMBER) {
        if (U_SUCCESS(ec)) {
            ec = U_ILLEGAL_ARGUMENT_ERROR;
        }
        return 0;
    } else {
        return getOffset(era, year, month, dom, dow, millis,
                         Grego::monthLength(year, month),
                         ec);
    }
}

/**
 * TimeZone API.
 */
int32_t OlsonTimeZone::getOffset(uint8_t era, int32_t year, int32_t month,
                                 int32_t dom, uint8_t dow,
                                 int32_t millis, int32_t monthLength,
                                 UErrorCode& ec) const {
    if (U_FAILURE(ec)) {
        return 0;
    }

    if ((era != GregorianCalendar::AD && era != GregorianCalendar::BC)
        || month < UCAL_JANUARY
        || month > UCAL_DECEMBER
        || dom < 1
        || dom > monthLength
        || dow < UCAL_SUNDAY
        || dow > UCAL_SATURDAY
        || millis < 0
        || millis >= U_MILLIS_PER_DAY
        || monthLength < 28
        || monthLength > 31) {
        ec = U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    if (era == GregorianCalendar::BC) {
        year = -year;
    }

    if (year > finalYear) { // [sic] >, not >=; see above
        U_ASSERT(finalZone != 0);
        return finalZone->getOffset(era, year, month, dom, dow,
                                    millis, monthLength, ec);
    }

    // Compute local epoch seconds from input fields
    double time = Grego::fieldsToDay(year, month, dom) * SECONDS_PER_DAY +
        uprv_floor(millis / (double) U_MILLIS_PER_SECOND);

    return zoneOffset(findTransition(time, TRUE)) * U_MILLIS_PER_SECOND;
}

/**
 * TimeZone API.
 */
void OlsonTimeZone::getOffset(UDate date, UBool local, int32_t& rawoff,
                              int32_t& dstoff, UErrorCode& ec) const {
    if (U_FAILURE(ec)) {
        return;
    }

    // The check against finalMillis will suffice most of the time, except
    // for the case in which finalMillis == DBL_MAX, date == DBL_MAX,
    // and finalZone == 0.  For this case we add "&& finalZone != 0".
    if (date >= finalMillis && finalZone != 0) {
        int32_t year, month, dom, dow;
        double days = uprv_floor(date / U_MILLIS_PER_DAY);
        
        Grego::dayToFields(days, year, month, dom, dow);

        int32_t millis = (int32_t) (date - days * U_MILLIS_PER_DAY);
        rawoff = finalZone->getRawOffset();

        if (!local) {
            // Adjust from GMT to local
            date += rawoff;
            double days2 = uprv_floor(date / U_MILLIS_PER_DAY);
            millis = (int32_t) (date - days2 * U_MILLIS_PER_DAY);
            if (days2 != days) {
                Grego::dayToFields(days2, year, month, dom, dow);
            }
        }

        dstoff = finalZone->getOffset(
            GregorianCalendar::AD, year, month,
            dom, (uint8_t) dow, millis, ec) - rawoff;
        return;
    }

    double secs = uprv_floor(date / U_MILLIS_PER_SECOND);
    int16_t i = findTransition(secs, local);
    rawoff = rawOffset(i) * U_MILLIS_PER_SECOND;
    dstoff = dstOffset(i) * U_MILLIS_PER_SECOND;
}

/**
 * TimeZone API.
 */
void OlsonTimeZone::setRawOffset(int32_t /*offsetMillis*/) {
    // We don't support this operation, since OlsonTimeZones are
    // immutable (except for the ID, which is in the base class).

    // Nothing to do!
}

/**
 * TimeZone API.
 */
int32_t OlsonTimeZone::getRawOffset() const {
    UErrorCode ec = U_ZERO_ERROR;
    int32_t raw, dst;
    getOffset((double) uprv_getUTCtime() * U_MILLIS_PER_SECOND,
              FALSE, raw, dst, ec);
    return raw;
}

/**
 * Find the smallest i (in 0..transitionCount-1) such that time >=
 * transition(i), where transition(i) is either the GMT or the local
 * transition time, as specified by `local'.
 * @param time epoch seconds, either GMT or local wall
 * @param local if TRUE, `time' is in local wall units, otherwise it
 * is GMT
 * @return an index i, where 0 <= i < transitionCount, and
 * transition(i) <= time < transition(i+1), or i == 0 if
 * transitionCount == 0 or time < transition(0).
 */
int16_t OlsonTimeZone::findTransition(double time, UBool local) const {
    int16_t i = 0;
    
    if (transitionCount != 0) {
        // Linear search from the end is the fastest approach, since
        // most lookups will happen at/near the end.
        for (i = transitionCount - 1; i > 0; --i) {
            int32_t transition = transitionTimes[i];
            if (local) {
                transition += zoneOffset(typeData[i]);
            }
            if (time >= transition) {
                break;
            }
        }

        U_ASSERT(i>=0 && i<transitionCount);

        // Check invariants for GMT times; if these pass for GMT times
        // the local logic should be working too.
        U_ASSERT(local || time < transitionTimes[0] || time >= transitionTimes[i]);
        U_ASSERT(local || i == transitionCount-1 || time < transitionTimes[i+1]);

        i = typeData[i];
    }

    U_ASSERT(i>=0 && i<typeCount);
    
    return i;
}

/**
 * TimeZone API.
 */
UBool OlsonTimeZone::useDaylightTime() const {
    // If DST was observed in 1942 (for example) but has never been
    // observed from 1943 to the present, most clients will expect
    // this method to return FALSE.  This method determines whether
    // DST is in use in the current year (at any point in the year)
    // and returns TRUE if so.

    int32_t days = Math::floorDivide(uprv_getUTCtime(), SECONDS_PER_DAY); // epoch days

    int32_t year, month, dom, dow;
    
    Grego::dayToFields(days, year, month, dom, dow);

    if (year > finalYear) { // [sic] >, not >=; see above
        U_ASSERT(finalZone != 0 && finalZone->useDaylightTime());
        return TRUE;
    }

    // Find start of this year, and start of next year
    int32_t start = (int32_t) Grego::fieldsToDay(year, 0, 1) * SECONDS_PER_DAY;    
    int32_t limit = (int32_t) Grego::fieldsToDay(year+1, 0, 1) * SECONDS_PER_DAY;    

    // Return TRUE if DST is observed at any time during the current
    // year.
    for (int16_t i=0; i<transitionCount; ++i) {
        if (transitionTimes[i] >= limit) {
            break;
        }
        if (transitionTimes[i] >= start &&
            dstOffset(typeData[i]) != 0) {
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * TimeZone API.
 */
UBool OlsonTimeZone::inDaylightTime(UDate date, UErrorCode& ec) const {
    int32_t raw, dst;
    getOffset(date, FALSE, raw, dst, ec);
    return dst != 0;
}

U_NAMESPACE_END

#endif // !UCONFIG_NO_FORMATTING

//eof

--- NEW FILE: olsontz.h ---
/*
**********************************************************************
* Copyright (c) 2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: July 21 2003
* Since: ICU 2.8
**********************************************************************
*/
#ifndef OLSONTZ_H
#define OLSONTZ_H

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/timezone.h"

struct UResourceBundle;

U_NAMESPACE_BEGIN

class SimpleTimeZone;

/**
 * A time zone based on the Olson database.  Olson time zones change
 * behavior over time.  The raw offset, rules, presence or absence of
 * daylight savings time, and even the daylight savings amount can all
 * vary.
 *
 * This class uses a resource bundle named "zoneinfo".  Zoneinfo is a
 * table containing different kinds of resources.  In several places,
 * zones are referred to using integers.  A zone's integer is a number
 * from 0..n-1, where n is the number of zones, with the zones sorted
 * in lexicographic order.
 *
 * 1. Zones.  These have keys corresponding to the Olson IDs, e.g.,
 * "Asia/Shanghai".  Each resource describes the behavior of the given
 * zone.  Zones come in several formats, which are differentiated
 * based on length.
 *
 *  a. Alias (int, length 1).  An alias zone is an int resource.  The
 *  integer is the zone number of the target zone.  The key of this
 *  resource is an alternate name for the target zone.  Aliases
 *  represent Olson links and ICU compatibility IDs.
 *
 *  b. Simple zone (array, length 3).  The three subelements are:
 *
 *   i. An intvector of transitions.  These are given in epoch
 *   seconds.  This may be an empty invector (length 0).  If the
 *   transtions list is empty, then the zone's behavior is fixed and
 *   given by the offset list, which will contain exactly one pair.
 *   Otherwise each transtion indicates a time after which (inclusive)
 *   the associated offset pair is in effect.
 *
 *   ii. An intvector of offsets.  These are in pairs of raw offset /
 *   DST offset, in units of seconds.  There will be at least one pair
 *   (length >= 2 && length % 2 == 0).
 *
 *   iii. A binary resource.  This is of the same length as the
 *   transitions vector, so length may be zero.  Each unsigned byte
 *   corresponds to one transition, and has a value of 0..n-1, where n
 *   is the number of pairs in the offset vector.  This forms a map
 *   between transitions and offset pairs.
 *
 *  c. Simple zone with aliases (array, length 4).  This is like a
 *  simple zone, but also contains a fourth element:
 *
 *   iv. An intvector of aliases.  This list includes this zone
 *   itself, and lists all aliases of this zone.
 *
 *  d. Complex zone (array, length 5).  This is like a simple zone,
 *  but contains two more elements:
 *
 *   iv. A string, giving the name of a rule.  This is the "final
 *   rule", which governs the zone's behavior beginning in the "final
 *   year".  The rule ID is given without leading underscore, e.g.,
 *   "EU".
 *
 *   v. An intvector of length 2, containing the raw offset for the
 *   final rule (in seconds), and the final year.  The final rule
 *   takes effect for years >= the final year.
 *
 *  e. Complex zone with aliases (array, length 6).  This is like a
 *  complex zone, but also contains a sixth element:
 * 
 *   vi. An intvector of aliases.  This list includes this zone
 *   itself, and lists all aliases of this zone.
 *
 * 2. Rules.  These have keys corresponding to the Olson rule IDs,
 * with an underscore prepended, e.g., "_EU".  Each resource describes
 * the behavior of the given rule using an intvector, containing the
 * onset list, the cessation list, and the DST savings.  The onset and
 * cessation lists consist of the month, dowim, dow, time, and time
 * mode.  The end result is that the 11 integers describing the rule
 * can be passed directly into the SimpleTimeZone 13-argument
 * constructor (the other two arguments will be the raw offset, taken
 * from the complex zone element 5, and the ID string, which is not
 * used), with the times and the DST savings multiplied by 1000 to
 * scale from seconds to milliseconds.
 *
 * 3. Countries.  These have keys corresponding to the 2-letter ISO
 * country codes, with a percent sign prepended, e.g., "%US".  Each
 * resource is an intvector listing the zones associated with the
 * given country.  The special entry "%" corresponds to "no country",
 * that is, the category of zones assigned to no country in the Olson
 * DB.
 *
 * 4. Metadata.  Metadata is stored under the key "_".  It is an
 * intvector of length three containing the number of zones resources,
 * rule resources, and country resources.  For the purposes of this
 * count, the metadata entry itself is considered a rule resource,
 * since its key begins with an underscore.
 */
class U_I18N_API OlsonTimeZone: public TimeZone {
 public:
    /**
     * Construct from a resource bundle.
     * @param top the top-level zoneinfo resource bundle.  This is used
     * to lookup the rule that `res' may refer to, if there is one.
     * @param res the resource bundle of the zone to be constructed
     * @param ec input-output error code
     */
    OlsonTimeZone(const UResourceBundle* top,
                  const UResourceBundle* res, UErrorCode& ec);

    /**
     * Copy constructor
     */
    OlsonTimeZone(const OlsonTimeZone& other);

    /**
     * Destructor
     */
    virtual ~OlsonTimeZone();

    /**
     * Assignment operator
     */
    OlsonTimeZone& operator=(const OlsonTimeZone& other);

    /**
     * Returns true if the two TimeZone objects are equal.
     */
    virtual UBool operator==(const TimeZone& other) const;

    /**
     * TimeZone API.
     */
    virtual TimeZone* clone() const;

    /**
     * TimeZone API.
     */
    static UClassID getStaticClassID();

    /**
     * TimeZone API.
     */
    virtual UClassID getDynamicClassID() const;
    
    /**
     * TimeZone API.  Do not call this; prefer getOffset(UDate,...).
     */
    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month,
                              int32_t day, uint8_t dayOfWeek,
                              int32_t millis, UErrorCode& ec) const;

    /**
     * TimeZone API.  Do not call this; prefer getOffset(UDate,...).
     */
    virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month,
                              int32_t day, uint8_t dayOfWeek,
                              int32_t millis, int32_t monthLength,
                              UErrorCode& ec) const;

    /**
     * TimeZone API.
     */
    virtual void getOffset(UDate date, UBool local, int32_t& rawOffset,
                   int32_t& dstOffset, UErrorCode& ec) const;

    /**
     * TimeZone API.  This method has no effect since objects of this
     * class are quasi-immutable (the base class allows the ID to be
     * changed).
     */
    virtual void setRawOffset(int32_t offsetMillis);

    /**
     * TimeZone API.  For a historical zone, the raw offset can change
     * over time, so this API is not useful.  In order to approximate
     * expected behavior, this method returns the raw offset for the
     * current moment in time.
     */
    virtual int32_t getRawOffset() const;

    /**
     * TimeZone API.  For a historical zone, whether DST is used or
     * not varies over time.  In order to approximate expected
     * behavior, this method returns TRUE if DST is observed at any
     * point in the current year.
     */
    virtual UBool useDaylightTime() const;

    /**
     * TimeZone API.
     */
    virtual UBool inDaylightTime(UDate date, UErrorCode& ec) const;

 protected:
    /**
     * Default constructor.  Creates a time zone with an empty ID and
     * a fixed GMT offset of zero.
     */
    OlsonTimeZone();

 private:

    void constructEmpty();

    int16_t findTransition(double time, UBool local) const;

    int32_t zoneOffset(int16_t index) const;
    int32_t rawOffset(int16_t index) const;
    int32_t dstOffset(int16_t index) const;

    /**
     * Number of transitions, 0..~370
     */
    int16_t transitionCount;

    /**
     * Number of types, 1..255
     */
    int16_t typeCount;

    /**
     * Time of each transition in seconds from 1970 epoch.
     * Length is transitionCount int32_t's.
     */
    const int32_t *transitionTimes; // alias into res; do not delete

    /**
     * Offset from GMT in seconds for each type.
     * Length is typeCount int32_t's.
     */
    const int32_t *typeOffsets; // alias into res; do not delete

    /**
     * Type description data, consisting of transitionCount uint8_t
     * type indices (from 0..typeCount-1).
     * Length is transitionCount int8_t's.
     */
    const uint8_t *typeData; // alias into res; do not delete

    /**
     * The last year for which the transitions data are to be used
     * rather than the finalZone.  If there is no finalZone, then this
     * is set to INT32_MAX.  NOTE: This corresponds to the year _before_
     * the one indicated by finalMillis.
     */
    int32_t finalYear;

    /**
     * The millis for the start of the first year for which finalZone
     * is to be used, or DBL_MAX if finalZone is 0.  NOTE: This is
     * 0:00 GMT Jan 1, <finalYear + 1> (not <finalMillis>).
     */
    double finalMillis;

    /**
     * A SimpleTimeZone that governs the behavior for years > finalYear.
     * If and only if finalYear == INT32_MAX then finalZone == 0.
     */
    SimpleTimeZone *finalZone; // owned, may be NULL

};

inline int32_t
OlsonTimeZone::zoneOffset(int16_t index) const {
    index <<= 1;
    return typeOffsets[index] + typeOffsets[index+1];
}

inline int32_t
OlsonTimeZone::rawOffset(int16_t index) const {
    return typeOffsets[(uint32_t)(index << 1)];
}

inline int32_t
OlsonTimeZone::dstOffset(int16_t index) const {
    return typeOffsets[(uint32_t)((index << 1) + 1)];
}

U_NAMESPACE_END

#endif // !UCONFIG_NO_FORMATTING
#endif // OLSONTZ_H

//eof

--- NEW FILE: ucurrimp.h ---
/*
**********************************************************************
* Copyright (c) 2002-2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
*/

#ifndef _UCURR_IMP_H_
#define _UCURR_IMP_H_

#include "unicode/utypes.h"

/**
 * Internal method.  Given a currency ISO code and a locale, return
 * the "static" currency name.  This is usually the same as the
 * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
 * format is applied to the number 2.0 (to yield the more common
 * plural) to return a static name.
 *
 * This is used for backward compatibility with old currency logic in
 * DecimalFormat and DecimalFormatSymbols.
 */
U_CAPI void
uprv_getStaticCurrencyName(const UChar* iso, const char* loc,
                           UnicodeString& result, UErrorCode& ec);

#endif /* #ifndef _UCURR_IMP_H_ */

//eof

--- NEW FILE: ulocdata.c ---
/*
******************************************************************************
*                                                                            *
* Copyright (C) 2003, International Business Machines                        *
*                Corporation and others. All Rights Reserved.                *
*                                                                            *
******************************************************************************
*   file name:  ulocdata.c
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 2003Oct21
*   created by: Ram Viswanadha
*/

#include "unicode/ulocdata.h"

#define EXEMPLAR_CHARS      "ExemplarCharacters"
#define MEASUREMENT_SYSTEM  "MeasurementSystem"
#define PAPER_SIZE          "PaperSize"

U_CAPI USet* U_EXPORT2 
ulocdata_getExemplarSet(USet *fillIn, const char *localeID, UErrorCode *status){
    
    UResourceBundle *bundle = NULL;
    const UChar *exemplarChars = NULL;
    int32_t len = 0;

    if(status == NULL || U_FAILURE(*status)){
        return NULL;
    }
    
    bundle = ures_open(NULL, localeID, status);
    
    exemplarChars = ures_getStringByKey(bundle, EXEMPLAR_CHARS, &len, status);
    
    if(fillIn != NULL){
        uset_applyPattern(fillIn, exemplarChars, len, 
                          USET_IGNORE_SPACE, status);
    }else{
        fillIn = uset_openPattern(exemplarChars, len, status);
    }
    
    ures_close(bundle);

    return fillIn;

}

U_CAPI UMeasurementSystem U_EXPORT2
ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
    
    UResourceBundle* bundle=NULL;
    UResourceBundle* measurement=NULL;
    UMeasurementSystem system = UMS_LIMIT; 
    
    if(status == NULL || U_FAILURE(*status)){
        return system;
    }
    
    bundle = ures_open(NULL, localeID, status);

    measurement = ures_getByKey(bundle, MEASUREMENT_SYSTEM, NULL, status);

    system = (UMeasurementSystem) ures_getInt(measurement, status);

    ures_close(bundle);
    ures_close(measurement);

    return system;

}

U_CAPI void U_EXPORT2
ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
    UResourceBundle* bundle=NULL;
    UResourceBundle* paperSizeBundle = NULL;
    const int32_t* paperSize=NULL;
    int32_t len = 0;

    if(status == NULL || U_FAILURE(*status)){
        return;
    }
    
    bundle = ures_open(NULL, localeID, status);
    paperSizeBundle = ures_getByKey(bundle, PAPER_SIZE, NULL, status);
    paperSize = ures_getIntVector(paperSizeBundle, &len,  status);
    
    if(U_SUCCESS(*status)){
        if(len < 2){
            *status = U_INTERNAL_PROGRAM_ERROR;
        }else{
            *height = paperSize[0];
            *width  = paperSize[1];
        }
    }
    
    ures_close(bundle);
    ures_close(paperSizeBundle);
    
}

Index: Makefile.in
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/Makefile.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Makefile.in	10 Sep 2003 02:42:22 -0000	1.5
+++ Makefile.in	6 Apr 2004 10:08:44 -0000	1.6
@@ -15,6 +15,7 @@
 
 ## All the flags and other definitions are included here.
 include $(top_builddir)/icudefs.mk
+-include Makefile.local
 
 ## Build directory information
 subdir = i18n
@@ -27,13 +28,17 @@
 TARGET_STUBNAME=i18n
 
 ifneq ($(ENABLE_STATIC),)
-TARGET = $(LIBICU)$(TARGET_STUBNAME)$(ICULIBSUFFIX).a
+TARGET = $(LIBSICU)$(TARGET_STUBNAME)$(ICULIBSUFFIX).$(A)
 endif
 
 ifneq ($(ENABLE_SHARED),)
 SO_TARGET = $(LIBICU)$(TARGET_STUBNAME)$(ICULIBSUFFIX).$(SO)
 ALL_SO_TARGETS = $(SO_TARGET) $(MIDDLE_SO_TARGET) $(FINAL_SO_TARGET)
 
+ifeq ($(ENABLE_SO_VERSION_DATA),1)
+SO_VERSION_DATA = i18n.res
+endif
+
 ifeq ($(OS390BATCH),1)
 BATCH_TARGET = $(BATCH_I18N_TARGET)
 BATCH_LIBS = $(BATCH_LIBICUUC) -lm
@@ -53,20 +58,20 @@
 
 OBJECTS = ucln_in.o \
 fmtable.o format.o msgfmt.o umsg.o numfmt.o unum.o decimfmt.o dcfmtsym.o \
+ucurr.o digitlst.o \
 choicfmt.o datefmt.o smpdtfmt.o dtfmtsym.o udat.o \
-ucal.o calendar.o gregocal.o timezone.o simpletz.o \
-buddhcal.o japancal.o \
+nfrs.o nfrule.o nfsubs.o rbnf.o \
+ucal.o calendar.o gregocal.o timezone.o simpletz.o olsontz.o \
+astro.o buddhcal.o islamcal.o japancal.o gregoimp.o hebrwcal.o chnsecal.o \
 sortkey.o bocsu.o coleitr.o coll.o ucoleitr.o \
 ucol.o ucol_bld.o ucol_cnt.o ucol_elm.o ucol_tok.o ucol_wgt.o tblcoll.o \
 strmatch.o usearch.o search.o stsearch.o \
-unifltlg.o translit.o utrans.o \
+unifltlg.o translit.o utrans.o esctrn.o unesctrn.o \
+funcrepl.o strrepl.o tridpars.o \
 cpdtrans.o hextouni.o rbt.o rbt_data.o rbt_pars.o rbt_rule.o rbt_set.o \
 nultrans.o remtrans.o titletrn.o tolowtrn.o toupptrn.o anytrans.o \
 name2uni.o uni2name.o unitohex.o nortrans.o quant.o transreg.o \
-nfrs.o nfrule.o nfsubs.o rbnf.o esctrn.o unesctrn.o \
-funcrepl.o strrepl.o tridpars.o \
-ucurr.o \
-regexcmp.o rematch.o repattrn.o regexst.o
+regexcmp.o rematch.o repattrn.o regexst.o ulocdata.o
 
 
 STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))
@@ -129,7 +134,7 @@
 
 clean-local:
 	test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
-	$(RMV) $(OBJECTS) $(STATIC_OBJECTS) $(ALL_TARGETS)
+	$(RMV) $(OBJECTS) $(STATIC_OBJECTS) $(ALL_TARGETS) $(SO_VERSION_DATA)
 
 distclean-local: clean-local
 	$(RMV) Makefile
@@ -146,7 +151,7 @@
 endif
 
 ifneq ($(ENABLE_SHARED),)
-$(FINAL_SO_TARGET): $(OBJECTS)
+$(FINAL_SO_TARGET): $(OBJECTS) $(SO_VERSION_DATA)
 	$(SHLIB.cc) $(LD_SONAME) $(OUTOPT)$@ $^ $(LIBS)
 
 ifeq ($(OS390BATCH),1)

Index: anytrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/anytrans.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- anytrans.cpp	10 Sep 2003 02:42:22 -0000	1.1
+++ anytrans.cpp	6 Apr 2004 10:08:45 -0000	1.2
@@ -170,7 +170,7 @@
 //------------------------------------------------------------
 // AnyTransliterator
 
-const char AnyTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AnyTransliterator)
 
 AnyTransliterator::AnyTransliterator(const UnicodeString& id,
                                      const UnicodeString& theTarget,

Index: anytrans.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/anytrans.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- anytrans.h	10 Sep 2003 02:42:22 -0000	1.1
+++ anytrans.h	6 Apr 2004 10:08:45 -0000	1.2
@@ -1,6 +1,6 @@
 /*
 *****************************************************************
-* Copyright (c) 2002, International Business Machines Corporation
+* Copyright (c) 2002-2003, International Business Machines Corporation
 * and others.  All Rights Reserved.
 *****************************************************************
 * $Source$ 
@@ -52,12 +52,6 @@
      */
     UScriptCode targetScript;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
 public:
     
     /**
@@ -86,14 +80,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
 private:
 

Index: buddhcal.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/buddhcal.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- buddhcal.cpp	10 Sep 2003 02:42:22 -0000	1.1
+++ buddhcal.cpp	6 Apr 2004 10:08:45 -0000	1.2
@@ -92,14 +92,13 @@
 BuddhistCalendar::monthLength(int32_t month) const
 {
     UErrorCode status = U_ZERO_ERROR;
-    int32_t year = internalGet(UCAL_YEAR);
     // ignore era
     return GregorianCalendar::monthLength(month, getGregorianYear(status));
 }
 
 int32_t BuddhistCalendar::internalGetEra() const
 {
-    return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : BE;  
+  return internalGet(UCAL_ERA, BE);
 }
 
 int32_t
@@ -117,9 +116,47 @@
   return year + kBuddhistEraStart;
 }
 
+int32_t BuddhistCalendar::handleGetExtendedYear()
+{
+  int32_t year;
+  if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
+    year = internalGet(UCAL_EXTENDED_YEAR, 1);
+  } else {
+    // Ignore the era, as there is only one
+    year = internalGet(UCAL_YEAR, 1);
+  }
+  return year;
+}
+
+int32_t BuddhistCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
+
+                                                   UBool useMonth) const
+{
+  return GregorianCalendar::handleComputeMonthStart(eyear+kBuddhistEraStart, month, useMonth);
+}
+
+void BuddhistCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
+{
+  GregorianCalendar::handleComputeFields(julianDay, status);
+  int32_t y = internalGet(UCAL_EXTENDED_YEAR) - kBuddhistEraStart;
+  internalSet(UCAL_EXTENDED_YEAR, y);
+  internalSet(UCAL_ERA, 0);
+  internalSet(UCAL_YEAR, y);
+}
+
+int32_t BuddhistCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
+{
+  if(field == UCAL_ERA) {
+    return BE;
+  } else {
+    return GregorianCalendar::handleGetLimit(field,limitType);
+  }
+}
+
+#if 0
 void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
 {
-  GregorianCalendar::timeToFields(theTime, quick, status);
+  //Calendar::timeToFields(theTime, quick, status);
 
   int32_t era = internalGet(UCAL_ERA);
   int32_t year = internalGet(UCAL_YEAR);
@@ -138,6 +175,7 @@
   internalSet(UCAL_ERA, era);
   internalSet(UCAL_YEAR, year);
 }
+#endif
 
 void BuddhistCalendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status)
 {
@@ -149,7 +187,6 @@
     
     if(field == UCAL_YEAR /* || field == UCAL_YEAR_WOY */) {
         int32_t year = internalGet(field);
-        int32_t era = internalGetEra();
 
         year += amount;
         

Index: buddhcal.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/buddhcal.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- buddhcal.h	10 Sep 2003 02:42:22 -0000	1.1
+++ buddhcal.h	6 Apr 2004 10:08:45 -0000	1.2
@@ -60,7 +60,7 @@
      * @param aLocale  The given locale.
      * @param success  Indicates the status of BuddhistCalendar object construction.
      *                 Returns U_ZERO_ERROR if constructed successfully.
-     * @stable ICU 2.0
+     * @internal
      */
     BuddhistCalendar(const Locale& aLocale, UErrorCode& success);
 
@@ -92,10 +92,7 @@
      */
     virtual Calendar* clone(void) const;
 
-    
-
 public:
-
     /**
      * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual
      * override. This method is to implement a simple version of RTTI, since not all C++
@@ -139,35 +136,128 @@
      * @param status  Output param set to success/failure code on exit. If any value
      *                previously set in the time field is invalid, this will be set to
      *                an error status.
-     * @draft ICU 2.6.
+     * @draft ICU 2.6
      */
     virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status);
 
     /**
-     * API overrides
-     * @private
+     * Gets the maximum value for the given time field. e.g. for DAY_OF_MONTH,
+     * 31.
+     *
+     * @param field  The given time field.
+     * @return       The maximum value for the given time field.
+     * @draft ICU 2.6
      */
     int32_t getMaximum(UCalendarDateFields field) const;
+
+    /**
+     * Gets the lowest maximum value for the given field if varies. Otherwise same as
+     * getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
+     *
+     * @param field  The given time field.
+     * @return       The lowest maximum value for the given time field.
+     * @draft ICU 2.6
+     */
     int32_t getLeastMaximum(UCalendarDateFields field) const;
+
+    /**
+     * @deprecated ICU 2.6 use UCalendarDateFields instead of EDateFields
+     */
     inline virtual int32_t getMaximum(EDateFields field) const { return getMaximum((UCalendarDateFields)field); }
+    /**
+     * @deprecated ICU 2.6 use UCalendarDateFields instead of EDateFields
+     */
     inline virtual int32_t getLeastMaximum(EDateFields field) const { return getLeastMaximum((UCalendarDateFields)field); }
+    /**
+     * @deprecated ICU 2.6 use UCalendarDateFields instead of EDateFields
+     */
     inline virtual void add(EDateFields field, int32_t amount, UErrorCode& status) { add((UCalendarDateFields)field, amount, status); }
 
-
 private:
     BuddhistCalendar(); // default constructor not implemented
 
     static const char fgClassID;
 
  protected:
+    /**
+     * Return the extended year defined by the current fields.  This will
+     * use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
+     * as UCAL_ERA) specific to the calendar system, depending on which set of
+     * fields is newer.
+     * @return the extended year
+     * @internal
+     */
+    virtual int32_t handleGetExtendedYear();
+    /**
+     * Subclasses may override this method to compute several fields
+     * specific to each calendar system.  
+     * @internal
+     */
+    virtual void handleComputeFields(int32_t julianDay, UErrorCode& status);
+    /**
+     * Subclass API for defining limits of different types.
+     * @param field one of the field numbers
+     * @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
+     * <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
+     * @internal
+     */
+    virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
+        /**
+     * Return the Julian day number of day before the first day of the
+     * given month in the given extended year.  Subclasses should override
+     * this method to implement their calendar system.
+     * @param eyear the extended year
+     * @param month the zero-based month, or 0 if useMonth is false
+     * @param useMonth if false, compute the day before the first day of
+     * the given year, otherwise, compute the day before the first day of
+     * the given month
+     * @param return the Julian day number of the day before the first
+     * day of the given month and year
+     * @internal
+     */
+    virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month,
+                                            UBool useMonth) const;
+
+    /**
+     * month length of current month
+     * @internal
+     */
     virtual int32_t monthLength(int32_t month) const; 
+    /**
+     * month length of month
+     * @internal
+     */
     virtual int32_t monthLength(int32_t month, int32_t year) const; 
+
+    /**
+     * month length of current month
+     * @internal
+     */
     int32_t getGregorianYear(UErrorCode& status) const;
 
+    /** 
+     * Calculate the era for internal computation
+     * @internal
+     */
     virtual int32_t internalGetEra() const;
-    virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
+
+    /**
+     * Returns TRUE because the Buddhist Calendar does have a default century
+     * @internal
+     */
     virtual UBool haveDefaultCentury() const;
+
+    /**
+     * Returns the date of the start of the default century
+     * @return start of century - in milliseconds since epoch, 1970
+     * @internal
+     */
     virtual UDate defaultCenturyStart() const;
+
+    /**
+     * Returns the year in which the default century begins
+     * @internal
+     */
     virtual int32_t defaultCenturyStartYear() const;
 
  private: // default century stuff.
@@ -189,27 +279,27 @@
      */
     static const int32_t    fgSystemDefaultCenturyYear;
 
+    /**
+     * start of default century, as a date
+     */
     static const UDate        fgSystemDefaultCentury;
 
     /**
-     * Returns the beginning date of the 100-year window that dates with 2-digit years
-     * are considered to fall within.
-     * @return    the beginning date of the 100-year window that dates with 2-digit years
-     *            are considered to fall within.
+     * Returns the beginning date of the 100-year window that dates 
+     * with 2-digit years are considered to fall within.
      */
     UDate         internalGetDefaultCenturyStart(void) const;
 
     /**
-     * Returns the first year of the 100-year window that dates with 2-digit years
-     * are considered to fall within.
-     * @return    the first year of the 100-year window that dates with 2-digit years
-     *            are considered to fall within.
+     * Returns the first year of the 100-year window that dates with 
+     * 2-digit years are considered to fall within.
      */
     int32_t          internalGetDefaultCenturyStartYear(void) const;
 
     /**
-     * Initializes the 100-year window that dates with 2-digit years are considered
-     * to fall within so that its start date is 80 years before the current time.
+     * Initializes the 100-year window that dates with 2-digit years
+     * are considered to fall within so that its start date is 80 years
+     * before the current time.
      */
     static void  initializeSystemDefaultCentury(void);
 };

Index: calendar.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/calendar.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- calendar.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ calendar.cpp	6 Apr 2004 10:08:45 -0000	1.4
@@ -30,13 +30,18 @@
 
 #include "unicode/resbund.h"
 #include "unicode/gregocal.h"
+#include "gregoimp.h"
 #include "buddhcal.h"
 #include "japancal.h"
+#include "islamcal.h"
+#include "hebrwcal.h"
+#include "chnsecal.h"
 #include "unicode/calendar.h"
 #include "cpputils.h"
[...2241 lines suppressed...]
+Calendar::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const {
+    U_LOCALE_BASED(locBased, *this);
+    return locBased.getLocaleID(type, status);
+}
 
 U_NAMESPACE_END
 
+// INTERNAL - for cleanup
+// clean up the astronomical data & cache
+U_CFUNC UBool calendar_islamic_cleanup(void);
+U_CFUNC UBool calendar_hebrew_cleanup(void);
+U_CFUNC UBool calendar_astro_cleanup(void);
+
 U_CFUNC UBool calendar_cleanup(void) {
+  calendar_islamic_cleanup();
+  calendar_hebrew_cleanup();
+  calendar_astro_cleanup();
   if (gService) {
     delete gService;
     gService = NULL;

Index: choicfmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/choicfmt.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- choicfmt.cpp	10 Sep 2003 02:42:22 -0000	1.4
+++ choicfmt.cpp	6 Apr 2004 10:08:45 -0000	1.5
@@ -39,7 +39,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char        ChoiceFormat::fgClassID = 0; // Value is irrelevant
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ChoiceFormat)
 
 // Special characters used by ChoiceFormat.  There are two characters
 // used interchangeably to indicate <=.  Either is parsed, but only
@@ -52,8 +52,8 @@
 #define MINUS        ((UChar)0x002D)   /*-*/
 #define INFINITY     ((UChar)0x221E)
 
-const UChar ChoiceFormat::fgPositiveInfinity[] = {INFINITY, 0};
-const UChar ChoiceFormat::fgNegativeInfinity[] = {MINUS, INFINITY, 0};
+static const UChar gPositiveInfinity[] = {INFINITY, 0};
+static const UChar gNegativeInfinity[] = {MINUS, INFINITY, 0};
 #define POSITIVE_INF_STRLEN 1
 #define NEGATIVE_INF_STRLEN 2
 
@@ -322,9 +322,9 @@
 
             double limit;
             buf.trim();
-            if (!buf.compare(fgPositiveInfinity, POSITIVE_INF_STRLEN)) {
+            if (!buf.compare(gPositiveInfinity, POSITIVE_INF_STRLEN)) {
                 limit = uprv_getInfinity();
-            } else if (!buf.compare(fgNegativeInfinity, NEGATIVE_INF_STRLEN)) {
+            } else if (!buf.compare(gNegativeInfinity, NEGATIVE_INF_STRLEN)) {
                 limit = -uprv_getInfinity();
             } else {
                 limit = stod(buf);
@@ -566,6 +566,19 @@
 }
 
 // -------------------------------------
+// Formats an int64 number, it's actually formatted as
+// a double.  The returned format string may differ
+// from the input number because of this.
+
+UnicodeString&
+ChoiceFormat::format(int64_t number, 
+                     UnicodeString& appendTo, 
+                     FieldPosition& status) const
+{
+    return format((double) number, appendTo, status);
+}
+
+// -------------------------------------
 // Formats a long number, it's actually formatted as
 // a double.  The returned format string may differ
 // from the input number because of this.
@@ -626,10 +639,11 @@
 
     UnicodeString buffer;
     for (int32_t i = 0; i < cnt; i++) {
-        double objDouble = (objs[i].getType() == Formattable::kLong) ?
-            ((double) objs[i].getLong()) : objs[i].getDouble();
-        buffer.remove();
-        appendTo += format(objDouble, buffer, pos);
+        double objDouble = objs[i].getDouble(&status);
+        if (U_SUCCESS(status)) {
+            buffer.remove();
+            appendTo += format(objDouble, buffer, pos);
+        }
     }
 
     return appendTo;

Index: coleitr.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/coleitr.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- coleitr.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ coleitr.cpp	6 Apr 2004 10:08:46 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 1996-2001, International Business Machines Corporation and    *
+* Copyright (C) 1996-2003, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -38,7 +38,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char CollationElementIterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationElementIterator)
 
 /* synwee : public can't remove */
 int32_t const CollationElementIterator::NULLORDER = 0xffffffff;
@@ -98,8 +98,7 @@
     }
 
     // option comparison
-    if (!(m_data_->reset_ == that.m_data_->reset_ 
-          && m_data_->iteratordata_.coll == that.m_data_->iteratordata_.coll))
+    if (m_data_->iteratordata_.coll != that.m_data_->iteratordata_.coll)
     {
         return FALSE;
     }

Index: coll.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/coll.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- coll.cpp	10 Sep 2003 02:42:22 -0000	1.4
+++ coll.cpp	6 Apr 2004 10:08:46 -0000	1.5
@@ -59,7 +59,7 @@
 
 UBool
 CollatorFactory::visible(void) const {
-  return TRUE;
+    return TRUE;
 }
 
 //-------------------------------------------
@@ -75,8 +75,7 @@
 // -------------------------------------
 
 class ICUCollatorFactory : public ICUResourceBundleFactory {
-
-  virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
+    virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
 };
 
 UObject*
@@ -88,7 +87,7 @@
         // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
         // but for ICU rb resources we use the actual one since it will fallback again
         lkey.canonicalLocale(loc);
-
+        
         return Collator::makeInstance(loc, status);
     }
     return NULL;
@@ -97,44 +96,53 @@
 // -------------------------------------
 
 class ICUCollatorService : public ICULocaleService {
-    public:
+public:
     ICUCollatorService()
         : ICULocaleService("Collator")
     {
         UErrorCode status = U_ZERO_ERROR;
         registerFactory(new ICUCollatorFactory(), status);
     }
-
+    
     virtual UObject* cloneInstance(UObject* instance) const {
         return ((Collator*)instance)->clone();
     }
-
+    
     virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
         LocaleKey& lkey = (LocaleKey&)key;
-		if (actualID) {
-			lkey.canonicalID(*actualID);
-		}
-        Locale loc;
+        if (actualID) {
+            // Ugly Hack Alert! We return an empty actualID to signal
+            // to callers that this is a default object, not a "real"
+            // service-created object. (TODO remove in 3.0) [aliu]
+            actualID->truncate(0);
+        }
+        Locale loc("");
         lkey.canonicalLocale(loc);
         return Collator::makeInstance(loc, status);
     }
-
-	virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const {
-		UnicodeString ar;
-		if (actualReturn == NULL) {
-			actualReturn = &ar;
-		}
-		Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status);
-		if (result) {
-			const LocaleKey& lkey = (const LocaleKey&)key;
-			Locale canonicalLocale;
-			Locale currentLocale;
-
-			result->setLocales(lkey.canonicalLocale(canonicalLocale), 
-				LocaleUtility::initLocaleFromName(*actualReturn, currentLocale));
-		}
-		return result;
-	}
+    
+    virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const {
+        UnicodeString ar;
+        if (actualReturn == NULL) {
+            actualReturn = &ar;
+        }
+        Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status);
+        // Ugly Hack Alert! If the actualReturn length is zero, this
+        // means we got a default object, not a "real" service-created
+        // object.  We don't call setLocales() on a default object,
+        // because that will overwrite its correct built-in locale
+        // metadata (valid & actual) with our incorrect data (all we
+        // have is the requested locale). (TODO remove in 3.0) [aliu]
+        if (result && actualReturn->length() > 0) {
+            const LocaleKey& lkey = (const LocaleKey&)key;
+            Locale canonicalLocale("");
+            Locale currentLocale("");
+            
+            result->setLocales(lkey.canonicalLocale(canonicalLocale), 
+                LocaleUtility::initLocaleFromName(*actualReturn, currentLocale));
+        }
+        return result;
+    }
 
     virtual UBool isDefault() const {
         return countFactories() == 1;
@@ -150,27 +158,27 @@
 static ICULocaleService* 
 getService(void)
 {
-  UBool needInit;
-  {
-    Mutex mutex;
-    needInit = (UBool)(gService == NULL);
-  }
-  if(needInit) {
-    ICULocaleService *newservice = new ICUCollatorService();
-    if(newservice) {
-      Mutex mutex;
-      if(gService == NULL) {
-        gService = newservice;
-        newservice = NULL;
-      }
+    UBool needInit;
+    {
+        Mutex mutex;
+        needInit = (UBool)(gService == NULL);
     }
-    if(newservice) {
-      delete newservice;
-    } else {
-      ucln_i18n_registerCleanup();
+    if(needInit) {
+        ICULocaleService *newservice = new ICUCollatorService();
+        if(newservice) {
+            Mutex mutex;
+            if(gService == NULL) {
+                gService = newservice;
+                newservice = NULL;
+            }
+        }
+        if(newservice) {
+            delete newservice;
+        } else {
+            ucln_i18n_registerCleanup();
+        }
     }
-  }
-  return gService;
+    return gService;
 }
 
 // -------------------------------------
@@ -178,128 +186,143 @@
 static UBool
 hasService(void) 
 {
-  Mutex mutex;
-  return gService != NULL;
+    Mutex mutex;
+    return gService != NULL;
 }
 
 // -------------------------------------
 
 UCollator* 
 Collator::createUCollator(const char *loc,
-					   UErrorCode *status)
+                          UErrorCode *status)
 {
-	UCollator *result = 0;
-	if (status && U_SUCCESS(*status) && hasService()) {
-		Locale desiredLocale(loc);
-		Collator *col = (Collator*)gService->get(desiredLocale, *status);
-		if (col && col->getDynamicClassID() == RuleBasedCollator::getStaticClassID()) {
-			RuleBasedCollator *rbc = (RuleBasedCollator *)col;
-			if (!rbc->dataIsOwned) {
-				result = ucol_safeClone(rbc->ucollator, NULL, NULL, status);
-			} else {
-				result = rbc->ucollator;
-				rbc->ucollator = NULL; // to prevent free on delete
-			}
-		}
-		delete col;
-	}
-	return result;
+    UCollator *result = 0;
+    if (status && U_SUCCESS(*status) && hasService()) {
+        Locale desiredLocale(loc);
+        Collator *col = (Collator*)gService->get(desiredLocale, *status);
+        if (col && col->getDynamicClassID() == RuleBasedCollator::getStaticClassID()) {
+            RuleBasedCollator *rbc = (RuleBasedCollator *)col;
+            if (!rbc->dataIsOwned) {
+                result = ucol_safeClone(rbc->ucollator, NULL, NULL, status);
+            } else {
+                result = rbc->ucollator;
+                rbc->ucollator = NULL; // to prevent free on delete
+            }
+        }
+        delete col;
+    }
+    return result;
 }
 
 // Collator public methods -----------------------------------------------
 
 Collator* Collator::createInstance(UErrorCode& success) 
 {
-  if (U_FAILURE(success))
-    return 0;
-  return createInstance(Locale::getDefault(), success);
+    if (U_FAILURE(success))
+        return 0;
+    return createInstance(Locale::getDefault(), success);
 }
 
 Collator* Collator::createInstance(const Locale& desiredLocale,
                                    UErrorCode& status)
 {
-  if (U_FAILURE(status)) 
-    return 0;
-
-  if (hasService()) {
-    return (Collator*)gService->get(desiredLocale, status);
-  }
-  return makeInstance(desiredLocale, status);
+    if (U_FAILURE(status)) 
+        return 0;
+    
+    if (hasService()) {
+        Locale actualLoc;
+        Collator *result =
+            (Collator*)gService->get(desiredLocale, &actualLoc, status);
+        // Ugly Hack Alert! If the returned locale is empty (not root,
+        // but empty -- getName() == "") then that means the service
+        // returned a default object, not a "real" service object.  In
+        // that case, the locale metadata (valid & actual) is setup
+        // correctly already, and we don't want to overwrite it. (TODO
+        // remove in 3.0) [aliu]
+        if (*actualLoc.getName() != 0) {
+            result->setLocales(desiredLocale, actualLoc);
+        }
+        return result;
+    }
+    return makeInstance(desiredLocale, status);
 }
 
 
 Collator* Collator::makeInstance(const Locale&  desiredLocale, 
                                          UErrorCode& status)
 {
-  // A bit of explanation is required here. Although in the current 
-  // implementation
-  // Collator::createInstance() is just turning around and calling 
-  // RuleBasedCollator(Locale&), this will not necessarily always be the 
-  // case. For example, suppose we modify this code to handle a 
-  // non-table-based Collator, such as that for Thai. In this case, 
-  // createInstance() will have to be modified to somehow determine this fact
-  // (perhaps a field in the resource bundle). Then it can construct the 
-  // non-table-based Collator in some other way, when it sees that it needs 
-  // to.
-  // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS 
-  // return a valid collation object, if the system if functioning properly.  
-  // The reason is that it will fall back, use the default locale, and even 
-  // use the built-in default collation rules. THEREFORE, createInstance() 
-  // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN 
-  // ADVANCE that the given locale's collation is properly implemented as a 
-  // RuleBasedCollator.
-  // Currently, we don't do this...we always return a RuleBasedCollator, 
-  // whether it is strictly correct to do so or not, without checking, because 
-  // we currently have no way of checking.
-
-  RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale, 
-                                                       status);
-  /* test for NULL */
-  if (collation == 0) {
-      status = U_MEMORY_ALLOCATION_ERROR;
-      return 0;
-  }
-  if (U_FAILURE(status))
-  {
-    delete collation;
-    collation = 0;
-  }
-  return collation;
+    // A bit of explanation is required here. Although in the current 
+    // implementation
+    // Collator::createInstance() is just turning around and calling 
+    // RuleBasedCollator(Locale&), this will not necessarily always be the 
+    // case. For example, suppose we modify this code to handle a 
+    // non-table-based Collator, such as that for Thai. In this case, 
+    // createInstance() will have to be modified to somehow determine this fact
+    // (perhaps a field in the resource bundle). Then it can construct the 
+    // non-table-based Collator in some other way, when it sees that it needs 
+    // to.
+    // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS 
+    // return a valid collation object, if the system if functioning properly.  
+    // The reason is that it will fall back, use the default locale, and even 
+    // use the built-in default collation rules. THEREFORE, createInstance() 
+    // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN 
+    // ADVANCE that the given locale's collation is properly implemented as a 
+    // RuleBasedCollator.
+    // Currently, we don't do this...we always return a RuleBasedCollator, 
+    // whether it is strictly correct to do so or not, without checking, because 
+    // we currently have no way of checking.
+    
+    RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale, 
+        status);
+    /* test for NULL */
+    if (collation == 0) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return 0;
+    }
+    if (U_FAILURE(status))
+    {
+        delete collation;
+        collation = 0;
+    }
+    return collation;
 }
 
+#ifdef U_USE_COLLATION_OBSOLETE_2_6
 // !!! dlf the following is obsolete, ignore registration for this
 
 Collator *
 Collator::createInstance(const Locale &loc,
                          UVersionInfo version,
-                         UErrorCode &status) {
-  Collator *collator;
-  UVersionInfo info;
-
-  collator=new RuleBasedCollator(loc, status);
-  /* test for NULL */
-  if (collator == 0) {
-      status = U_MEMORY_ALLOCATION_ERROR;
-      return 0;
-  }
-
-  if(U_SUCCESS(status)) {
-    collator->getVersion(info);
-    if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) {
-      delete collator;
-      status=U_MISSING_RESOURCE_ERROR;
-      return 0;
+                         UErrorCode &status)
+{
+    Collator *collator;
+    UVersionInfo info;
+    
+    collator=new RuleBasedCollator(loc, status);
+    /* test for NULL */
+    if (collator == 0) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return 0;
     }
-  }
-  return collator;
+    
+    if(U_SUCCESS(status)) {
+        collator->getVersion(info);
+        if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) {
+            delete collator;
+            status=U_MISSING_RESOURCE_ERROR;
+            return 0;
+        }
+    }
+    return collator;
 }
+#endif
 
 // implement deprecated, previously abstract method
 Collator::EComparisonResult Collator::compare(const UnicodeString& source, 
                                     const UnicodeString& target) const
 {
-	UErrorCode ec = U_ZERO_ERROR;
-	return (Collator::EComparisonResult)compare(source, target, ec);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (Collator::EComparisonResult)compare(source, target, ec);
 }
 
 // implement deprecated, previously abstract method
@@ -307,8 +330,8 @@
                                     const UnicodeString& target,
                                     int32_t length) const
 {
-	UErrorCode ec = U_ZERO_ERROR;
-	return (Collator::EComparisonResult)compare(source, target, length, ec);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (Collator::EComparisonResult)compare(source, target, length, ec);
 }
 
 // implement deprecated, previously abstract method
@@ -316,52 +339,52 @@
                                     const UChar* target, int32_t targetLength) 
                                     const
 {
-	UErrorCode ec = U_ZERO_ERROR;
-	return (Collator::EComparisonResult)compare(source, sourceLength, target, targetLength, ec);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (Collator::EComparisonResult)compare(source, sourceLength, target, targetLength, ec);
 }
 
 UBool Collator::equals(const UnicodeString& source, 
-                          const UnicodeString& target) const
+                       const UnicodeString& target) const
 {
-  UErrorCode ec = U_ZERO_ERROR;
-  return (compare(source, target, ec) == UCOL_EQUAL);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (compare(source, target, ec) == UCOL_EQUAL);
 }
 
 UBool Collator::greaterOrEqual(const UnicodeString& source, 
-                                  const UnicodeString& target) const
+                               const UnicodeString& target) const
 {
-  UErrorCode ec = U_ZERO_ERROR;
-  return (compare(source, target, ec) != UCOL_LESS);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (compare(source, target, ec) != UCOL_LESS);
 }
 
 UBool Collator::greater(const UnicodeString& source, 
-                           const UnicodeString& target) const
+                        const UnicodeString& target) const
 {
-  UErrorCode ec = U_ZERO_ERROR;
-  return (compare(source, target, ec) == UCOL_GREATER);
+    UErrorCode ec = U_ZERO_ERROR;
+    return (compare(source, target, ec) == UCOL_GREATER);
 }
 
 // this API  ignores registered collators, since it returns an
 // array of indefinite lifetime
 const Locale* Collator::getAvailableLocales(int32_t& count) 
 {
-  return Locale::getAvailableLocales(count);
+    return Locale::getAvailableLocales(count);
 }
 
 UnicodeString& Collator::getDisplayName(const Locale& objectLocale,
-                                           const Locale& displayLocale,
-                                           UnicodeString& name)
+                                        const Locale& displayLocale,
+                                        UnicodeString& name)
 {
-  if (hasService()) {
-    return gService->getDisplayName(objectLocale.getName(), name, displayLocale);
-  }
-  return objectLocale.getDisplayName(displayLocale, name);
+    if (hasService()) {
+        return gService->getDisplayName(objectLocale.getName(), name, displayLocale);
+    }
+    return objectLocale.getDisplayName(displayLocale, name);
 }
 
 UnicodeString& Collator::getDisplayName(const Locale& objectLocale,
-                                           UnicodeString& name)
+                                        UnicodeString& name)
 {   
-  return getDisplayName(objectLocale, Locale::getDefault(), name);
+    return getDisplayName(objectLocale, Locale::getDefault(), name);
 }
 
 /* This is useless information */
@@ -381,7 +404,7 @@
 * is left to the child class.
 */
 Collator::Collator()
-    : UObject()
+: UObject()
 {
 }
 
@@ -396,7 +419,7 @@
 * @deprecated 2.4 use the default constructor instead
 */
 Collator::Collator(UCollationStrength, UNormalizationMode )
-    : UObject()
+: UObject()
 {
 }
 
@@ -409,20 +432,40 @@
 {
 }
 
+UBool Collator::operator==(const Collator& other) const
+{
+    return (UBool)(this == &other);
+}
+
+UBool Collator::operator!=(const Collator& other) const
+{
+    return (UBool)!(*this == other);
+}
+
 int32_t Collator::getBound(const uint8_t       *source,
-        int32_t             sourceLength,
-        UColBoundMode       boundType,
-        uint32_t            noOfLevels,
-        uint8_t             *result,
-        int32_t             resultLength,
-        UErrorCode          &status) {
-  return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status);
+                           int32_t             sourceLength,
+                           UColBoundMode       boundType,
+                           uint32_t            noOfLevels,
+                           uint8_t             *result,
+                           int32_t             resultLength,
+                           UErrorCode          &status)
+{
+    return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status);
 }
 
 void
 Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */) {
 }
 
+UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const
+{
+    if(U_FAILURE(status)) {
+        return NULL;
+    }
+    // everything can be changed
+    return new UnicodeSet(0, 0x10FFFF);
+}
+
 // -------------------------------------
 
 URegistryKey
@@ -440,41 +483,41 @@
 private:
     CollatorFactory* _delegate;
     Hashtable* _ids;
-
+    
 public:
     CFactory(CollatorFactory* delegate, UErrorCode& status) 
         : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
         , _delegate(delegate)
         , _ids(NULL)
     {
-		if (U_SUCCESS(status)) {
-			int32_t count = 0;
-			_ids = new Hashtable(status);
-			if (_ids) {
-				const UnicodeString * idlist = _delegate->getSupportedIDs(count, status);
-				for (int i = 0; i < count; ++i) {
-					_ids->put(idlist[i], (void*)this, status);
-					if (U_FAILURE(status)) {
-						delete _ids;
-						_ids = NULL;
-						return;
-					}
-				}
-			} else {
-				status = U_MEMORY_ALLOCATION_ERROR;
-			}
+        if (U_SUCCESS(status)) {
+            int32_t count = 0;
+            _ids = new Hashtable(status);
+            if (_ids) {
+                const UnicodeString * idlist = _delegate->getSupportedIDs(count, status);
+                for (int i = 0; i < count; ++i) {
+                    _ids->put(idlist[i], (void*)this, status);
+                    if (U_FAILURE(status)) {
+                        delete _ids;
+                        _ids = NULL;
+                        return;
+                    }
+                }
+            } else {
+                status = U_MEMORY_ALLOCATION_ERROR;
+            }
         }
     }
-
+    
     virtual ~CFactory()
     {
         delete _delegate;
         delete _ids;
     }
-
+    
     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
-
-  protected:
+    
+protected:
     virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
     {
         if (U_SUCCESS(status)) {
@@ -482,7 +525,7 @@
         }
         return NULL;
     }
-
+    
     virtual UnicodeString&
         getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
 };
@@ -494,7 +537,7 @@
         const LocaleKey& lkey = (const LocaleKey&)key;
         Locale validLoc;
         lkey.currentLocale(validLoc);
-		return _delegate->createCollator(validLoc);
+        return _delegate->createCollator(validLoc);
     }
     return NULL;
 }
@@ -533,13 +576,13 @@
 UBool 
 Collator::unregister(URegistryKey key, UErrorCode& status) 
 {
-  if (U_SUCCESS(status)) {
-    if (hasService()) {
-      return gService->unregister(key, status);
+    if (U_SUCCESS(status)) {
+        if (hasService()) {
+            return gService->unregister(key, status);
+        }
+        status = U_ILLEGAL_ARGUMENT_ERROR;
     }
-    status = U_ILLEGAL_ARGUMENT_ERROR;
-  }
-  return FALSE;
+    return FALSE;
 }
 
 // -------------------------------------
@@ -547,7 +590,7 @@
 StringEnumeration* 
 Collator::getAvailableLocales(void)
 {
-  return getService()->getAvailableLocales();
+    return getService()->getAvailableLocales();
 }
 
 // UCollator private data members ----------------------------------------
@@ -565,11 +608,11 @@
  * Release all static memory held by collator.
  */
 U_CFUNC UBool collator_cleanup(void) {
-  if (gService) {
-    delete gService;
-    gService = NULL;
-  }
-  return TRUE;
+    if (gService) {
+        delete gService;
+        gService = NULL;
+    }
+    return TRUE;
 }
 
 #endif /* #if !UCONFIG_NO_COLLATION */

Index: cpdtrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/cpdtrans.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cpdtrans.cpp	10 Sep 2003 02:42:22 -0000	1.4
+++ cpdtrans.cpp	6 Apr 2004 10:08:46 -0000	1.5
@@ -30,7 +30,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char CompoundTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CompoundTransliterator)
 
 /**
  * Constructs a new compound transliterator given an array of

Index: cpdtrans.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/cpdtrans.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cpdtrans.h	10 Sep 2003 02:42:22 -0000	1.1
+++ cpdtrans.h	6 Apr 2004 10:08:46 -0000	1.2
@@ -18,7 +18,7 @@
 
 U_NAMESPACE_BEGIN
 
-class U_I18N_API UVector;
+class U_COMMON_API UVector;
 class TransliteratorRegistry;
 
 /**
@@ -188,14 +188,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const;
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID();
+    static UClassID getStaticClassID();
 
 private:
 
@@ -243,21 +243,7 @@
     void freeTransliterators(void);
 
     void computeMaximumContextLength(void);
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
-
-inline UClassID
-CompoundTransliterator::getStaticClassID()
-{ return (UClassID)&fgClassID; }
-
-inline UClassID
-CompoundTransliterator::getDynamicClassID() const
-{ return CompoundTransliterator::getStaticClassID(); }
 
 U_NAMESPACE_END
 

Index: datefmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/datefmt.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- datefmt.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ datefmt.cpp	6 Apr 2004 10:08:46 -0000	1.4
@@ -25,6 +25,10 @@
 #include "unicode/datefmt.h"
 #include "unicode/smpdtfmt.h"
 
+#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
+#include <stdio.h>
+#endif
+
 // *****************************************************************************
 // class DateFormat
 // *****************************************************************************
@@ -193,7 +197,13 @@
 
     ParsePosition pos(0);
     UDate result = parse(text, pos);
-    if (pos.getIndex() == 0) status = U_ILLEGAL_ARGUMENT_ERROR;
+    if (pos.getIndex() == 0) {
+#if defined (U_DEBUG_CAL)
+      fprintf(stderr, "%s:%d - - failed to parse  - err index %d\n"
+              , __FILE__, __LINE__, pos.getErrorIndex() );
+#endif
+      status = U_ILLEGAL_ARGUMENT_ERROR;
+    }
     return result;
 }
 

Index: dcfmtsym.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/dcfmtsym.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dcfmtsym.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ dcfmtsym.cpp	6 Apr 2004 10:08:46 -0000	1.4
@@ -13,7 +13,7 @@
 *   03/18/97    clhuang     Implemented with C++ APIs.
 *   03/27/97    helena      Updated to pass the simple test after code review.
 *   08/26/97    aliu        Added currency/intl currency symbol support.
-*    07/20/98    stephen        Slightly modified initialization of monetarySeparator
+*   07/20/98    stephen     Slightly modified initialization of monetarySeparator
 ********************************************************************************
 */
  
@@ -26,6 +26,9 @@
 #include "unicode/decimfmt.h"
 #include "unicode/ucurr.h"
 #include "unicode/choicfmt.h"
+#include "ucurrimp.h"
+#include "cstring.h"
+#include "locbased.h"
 
 // *****************************************************************************
 // class DecimalFormatSymbols
@@ -33,9 +36,9 @@
  
 U_NAMESPACE_BEGIN
 
-const char DecimalFormatSymbols::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols)
 
-const char DecimalFormatSymbols::fgNumberElements[] = "NumberElements";
+static const char gNumberElements[] = "NumberElements";
 
 static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0};
 
@@ -43,18 +46,20 @@
 // Initializes this with the decimal format symbols in the default locale.
  
 DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
-    : UObject()
+    : UObject(),
+    locale()
 {
-    initialize(Locale::getDefault(), status, TRUE);
+    initialize(locale, status, TRUE);
 }
  
 // -------------------------------------
 // Initializes this with the decimal format symbols in the desired locale.
  
 DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
-    : UObject()
+    : UObject(),
+    locale(loc)
 {
-    initialize(loc, status);
+    initialize(locale, status);
 }
  
 // -------------------------------------
@@ -74,6 +79,8 @@
         // fastCopyFrom is safe, see docs on fSymbols
         fSymbols[(ENumberFormatSymbol)i].fastCopyFrom(source.fSymbols[(ENumberFormatSymbol)i]);
     }
+    uprv_strcpy(validLocale, source.validLocale);
+    uprv_strcpy(actualLocale, source.actualLocale);
 }
 
 // -------------------------------------
@@ -117,11 +124,13 @@
 DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status,
                                  UBool useLastResortData)
 {
-    if (U_FAILURE(status)) return;
+    *validLocale = *actualLocale = 0;
 
-    this->locale = loc;
+    if (U_FAILURE(status))
+        return;
 
-    ResourceBundle resource((char *)0, loc, status);
+    const char* locStr = loc.getName();
+    UResourceBundle *resource = ures_open((char *)0, locStr, &status);
     if (U_FAILURE(status))
     {
         // Initializes with last resort data if necessary.
@@ -130,61 +139,54 @@
             status = U_USING_FALLBACK_WARNING;
             initialize();
         }
-        return;
-    }
-
-    // Gets the number element array.
-    int32_t i = 0;
-    ResourceBundle numberElementsRes = resource.get(fgNumberElements, status);
-    int32_t numberElementsLength = numberElementsRes.getSize();
-
-    // If the array size is too small, something is wrong with the resource
-    // bundle, returns the failure error code.
-    if (numberElementsLength < 11) {
-        status = U_INVALID_FORMAT_ERROR;
-        return;
-    }
-
-    UnicodeString numberElements[kFormatSymbolCount];
-    for(i = 0; i<numberElementsLength; i++) {
-        numberElements[i].fastCopyFrom(numberElementsRes.getStringEx(i, status));
-    }
-
-    if (U_FAILURE(status)) {
-        return;
     }
+    else {
+        // Gets the number element array.
+        UResourceBundle *numberElementsRes = ures_getByKey(resource, gNumberElements, NULL, &status);
+        int32_t numberElementsLength = ures_getSize(numberElementsRes);
 
-    initialize(numberElements, numberElementsLength);
+        // If the array size is too small, something is wrong with the resource
+        // bundle, returns the failure error code.
+        if (numberElementsLength < 11 || U_FAILURE(status)) {
+            status = U_INVALID_FORMAT_ERROR;
+        }
+        else {
+            UnicodeString numberElements[kFormatSymbolCount];
+            int32_t i = 0;
+            for(i = 0; i<numberElementsLength; i++) {
+                int32_t len = 0;
+                const UChar *resUChars = ures_getStringByIndex(numberElementsRes, i, &len, &status);
+                numberElements[i].fastCopyFrom(UnicodeString(TRUE, resUChars, len));
+            }
 
+            if (U_SUCCESS(status)) {
+                initialize(numberElements, numberElementsLength);
 
-    // Obtain currency data from the currency API.  This is strictly
-    // for backward compatibility; we don't use DecimalFormatSymbols
-    // for currency data anymore.
-    UErrorCode ec = U_ZERO_ERROR; // don't propagate failures out
-    const char* l = loc.getName();
-    const UChar* curriso = ucurr_forLocale(l, &ec);
-    UBool isChoiceFormat;
-    int32_t len;
-    const UChar* currname = ucurr_getName(curriso, l, UCURR_SYMBOL_NAME,
-                                          &isChoiceFormat, &len, &ec);
-    if (U_SUCCESS(ec)) {
-        fSymbols[kIntlCurrencySymbol] = curriso;
+                // Obtain currency data from the currency API.  This is strictly
+                // for backward compatibility; we don't use DecimalFormatSymbols
+                // for currency data anymore.
+                UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
+                UChar curriso[4];
+                ucurr_forLocale(locStr, curriso, 4, &internalStatus);
 
-        // If this is a ChoiceFormat currency, then format an
-        // arbitrary value; pick something != 1; more common.
-        fSymbols[kCurrencySymbol].truncate(0);
-        if (isChoiceFormat) {
-            ChoiceFormat f(currname, ec);
-            if (U_SUCCESS(ec)) {
-                f.format(2.0, fSymbols[kCurrencySymbol]);
-            } else {
-                fSymbols[kCurrencySymbol] = fSymbols[kIntlCurrencySymbol];
+                // Reuse numberElements[0] as a temporary buffer
+                uprv_getStaticCurrencyName(curriso, locStr, numberElements[0], internalStatus);
+                if (U_SUCCESS(internalStatus)) {
+                    fSymbols[kIntlCurrencySymbol] = curriso;
+                    fSymbols[kCurrencySymbol] = numberElements[0];
+                }
+                /* else use the default values. */
             }
-        } else {
-            fSymbols[kCurrencySymbol] = UnicodeString(currname);
+
+            U_LOCALE_BASED(locBased, *this);
+            locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes,
+                                       ULOC_VALID_LOCALE, &status),
+                                  ures_getLocaleByType(numberElementsRes,
+                                       ULOC_ACTUAL_LOCALE, &status));
         }
+        ures_close(numberElementsRes);
     }
-    /* else use the default values. */
+    ures_close(resource);
 }
 
 // Initializes the DecimalFormatSymbol instance with the data obtained
@@ -200,7 +202,6 @@
     fSymbols[kZeroDigitSymbol].fastCopyFrom(numberElements[4]);
     fSymbols[kDigitSymbol].fastCopyFrom(numberElements[5]);
     fSymbols[kMinusSignSymbol].fastCopyFrom(numberElements[6]);
-    fSymbols[kPlusSignSymbol] = (UChar)0x002b; // '+' Hard coded for now; get from resource later
     fSymbols[kExponentialSymbol].fastCopyFrom(numberElements[7]);
     fSymbols[kPerMillSymbol].fastCopyFrom(numberElements[8]);
     fSymbols[kPadEscapeSymbol] = (UChar)0x002a; // '*' Hard coded for now; get from resource later
@@ -209,6 +210,13 @@
 
     // If there is a currency decimal, use it.
     fSymbols[kMonetarySeparatorSymbol].fastCopyFrom(numberElements[numberElementsLength >= 12 ? 11 : 0]);
+    if (numberElementsLength >= 13) {
+        fSymbols[kPlusSignSymbol].fastCopyFrom(numberElements[12]);
+    }
+    else {
+        /* This locale really needs to be updated. This locale is out of date. */
+        fSymbols[kPlusSignSymbol] = (UChar)0x002B;  /* + */
+    }
 
     // Default values until it's set later on.
     fSymbols[kCurrencySymbol] = (UChar)0xa4;            // 'OX' currency symbol
@@ -229,8 +237,8 @@
     fSymbols[kPercentSymbol] = (UChar)0x25;             // '%' percent sign
     fSymbols[kZeroDigitSymbol] = (UChar)0x30;           // '0' native 0 digit
     fSymbols[kDigitSymbol] = (UChar)0x23;               // '#' pattern digit
-    fSymbols[kMinusSignSymbol] = (UChar)0x2d;           // '-' minus sign
     fSymbols[kPlusSignSymbol] = (UChar)0x002b;          // '+' plus sign
+    fSymbols[kMinusSignSymbol] = (UChar)0x2d;           // '-' minus sign
     fSymbols[kCurrencySymbol] = (UChar)0xa4;            // 'OX' currency symbol
     fSymbols[kIntlCurrencySymbol] = INTL_CURRENCY_SYMBOL_STR;
     fSymbols[kMonetarySeparatorSymbol] = (UChar)0x2e;   // '.' monetary decimal separator
@@ -239,6 +247,12 @@
     fSymbols[kPadEscapeSymbol] = (UChar)0x2a;           // '*' pad escape symbol
     fSymbols[kInfinitySymbol] = (UChar)0x221e;          // 'oo' infinite
     fSymbols[kNaNSymbol] = (UChar)0xfffd;               // SUB NaN
+}
+
+Locale 
+DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
+    U_LOCALE_BASED(locBased, *this);
+    return locBased.getLocale(type, status);
 }
 
 U_NAMESPACE_END

Index: decimfmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/decimfmt.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- decimfmt.cpp	10 Sep 2003 02:42:22 -0000	1.6
+++ decimfmt.cpp	6 Apr 2004 10:08:46 -0000	1.7
@@ -48,6 +48,7 @@
 #include "unicode/dcfmtsym.h"
 #include "unicode/resbund.h"
 #include "unicode/uchar.h"
+#include "ucurrimp.h"
 #include "uprops.h"
 #include "digitlst.h"
 #include "cmemory.h"
@@ -76,37 +77,76 @@
 // class DecimalFormat
 // *****************************************************************************
 
-const char DecimalFormat::fgClassID = 0; // Value is irrelevant
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
 
 // Constants for characters used in programmatic (unlocalized) patterns.
-#ifndef __BORLANDC__
-const UChar DecimalFormat::kPatternZeroDigit           = 0x0030 /*'0'*/;
-const UChar DecimalFormat::kPatternGroupingSeparator   = 0x002C /*','*/;
-const UChar DecimalFormat::kPatternDecimalSeparator    = 0x002E /*'.'*/;
-const UChar DecimalFormat::kPatternPerMill             = 0x2030;
-const UChar DecimalFormat::kPatternPercent             = 0x0025 /*'%'*/;
-const UChar DecimalFormat::kPatternDigit               = 0x0023 /*'#'*/;
-const UChar DecimalFormat::kPatternSeparator           = 0x003B /*';'*/;
-const UChar DecimalFormat::kPatternExponent            = 0x0045 /*'E'*/;
-const UChar DecimalFormat::kPatternPlus                = 0x002B /*'+'*/;
-const UChar DecimalFormat::kPatternMinus               = 0x002D /*'-'*/;
-const UChar DecimalFormat::kPatternPadEscape           = 0x002A /*'*'*/;
-const UChar DecimalFormat::kCurrencySign               = 0x00A4;
-const UChar DecimalFormat::kQuote                      = 0x0027 /*'\''*/;
-#endif
-
-//const int8_t DecimalFormat::fgMaxDigit                  = 9;
+#define kPatternZeroDigit            ((UChar)0x0030) /*'0'*/
+#define kPatternGroupingSeparator    ((UChar)0x002C) /*','*/
+#define kPatternDecimalSeparator     ((UChar)0x002E) /*'.'*/
+#define kPatternPerMill              ((UChar)0x2030)
+#define kPatternPercent              ((UChar)0x0025) /*'%'*/
+#define kPatternDigit                ((UChar)0x0023) /*'#'*/
+#define kPatternSeparator            ((UChar)0x003B) /*';'*/
+#define kPatternExponent             ((UChar)0x0045) /*'E'*/
+#define kPatternPlus                 ((UChar)0x002B) /*'+'*/
+#define kPatternMinus                ((UChar)0x002D) /*'-'*/
+#define kPatternPadEscape            ((UChar)0x002A) /*'*'*/
+#define kQuote                       ((UChar)0x0027) /*'\''*/
+/**
+ * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
+ * is used in patterns and substitued with either the currency symbol,
+ * or if it is doubled, with the international currency symbol.  If the
+ * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
+ * replaced with the monetary decimal separator.
+ */
+#define kCurrencySign               ((UChar)0x00A4)
 
 const int32_t DecimalFormat::kDoubleIntegerDigits  = 309;
 const int32_t DecimalFormat::kDoubleFractionDigits = 340;
 
+const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
+#if 0
+class Test {
+private:
+	int32_t f;
+public:
+// 	void a(int arg);
+	void a(int32_t arg);
+ 	void a(int64_t arg);
+	void a(double arg);
+};
+
+//void Test::a(int arg) { f = (int32_t)arg; }
+void Test::a(int32_t arg) { f = arg; }
+void Test::a(int64_t arg) { f = (int32_t)arg; }
+void Test::a(double arg)  { f = (int32_t)arg; }
+
+static void test(uint64_t num) {
+	Test t;
+	int32_t zero32 = 0;
+	int64_t zero64 = 0;
+	double  zeroDbl = 0;
+
+	t.a((int32_t)0);
+	t.a((int64_t)0);
+	t.a((double)0);
+	t.a(0);
+	t.a(0.0);
+	t.a(0.0f);
+//	t.a(zero32);
+//	t.a(zero64);
+//	t.a(zeroDbl);
+//	t.a(num);
+}
+#endif
+
 /**
  * These are the tags we expect to see in normal resource bundle files associated
  * with a locale.
  */
 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns";
 
-static const UChar kDefaultPad = 0x0020; /* */
+#define kDefaultPad ((UChar)0x0020) /* */
 
 //------------------------------------------------------------------------------
 // Constructs a DecimalFormat instance in the default locale.
@@ -292,10 +332,16 @@
         return;
     }
 
-    if (symbolsToAdopt == NULL) {
-        setCurrencyForLocale(uloc_getDefault(), status);
+    if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
+        // If it looks like we are going to use a currency pattern
+        // then do the time consuming lookup.
+        if (symbolsToAdopt == NULL) {
+            setCurrencyForLocale(uloc_getDefault(), status);
+        } else {
+            setCurrencyForSymbols();
+        }
     } else {
-        setCurrencyForSymbols();
+        setCurrency(NULL);
     }
 
     applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
@@ -310,7 +356,8 @@
         // Trap an error in mapping locale to currency.  If we can't
         // map, then don't fail and set the currency to "".
         UErrorCode ec2 = U_ZERO_ERROR;
-        c = ucurr_forLocale(locale, &ec2);
+        UChar c[4];
+        ucurr_forLocale(locale, c, 4, &ec2);
     }
     setCurrency(c);
 }
@@ -582,6 +629,16 @@
                       UnicodeString& appendTo,
                       FieldPosition& fieldPosition) const
 {
+	return format((int64_t)number, appendTo, fieldPosition);
+}
+
+//------------------------------------------------------------------------------
+ 
+UnicodeString&
+DecimalFormat::format(int64_t number,
+                      UnicodeString& appendTo,
+                      FieldPosition& fieldPosition) const
+{
     DigitList digits;
 
     // Clears field positions.
@@ -598,19 +655,16 @@
     // check for this before multiplying, and if it happens we use doubles
     // instead, trading off accuracy for range.
     if (fRoundingIncrement != NULL
-        || (fMultiplier != 0 && (number > (INT32_MAX / fMultiplier)
-                              || number < (INT32_MIN / fMultiplier))))
+        || (fMultiplier != 0 && (number > (U_INT64_MAX / fMultiplier)
+                              || number < (U_INT64_MIN / fMultiplier))))
     {
         digits.set(((double)number) * fMultiplier,
-                   fUseExponentialNotation ?
-                            getMinimumIntegerDigits() + getMaximumFractionDigits() : 0,
+			precision(FALSE),
                    !fUseExponentialNotation);
     }
     else
     {
-        digits.set(number * fMultiplier,
-                   fUseExponentialNotation ?
-                            getMinimumIntegerDigits() + getMaximumFractionDigits() : 0);
+        digits.set(number * fMultiplier, precision(TRUE));
     }
 
     return subformat(appendTo, fieldPosition, digits, TRUE);
@@ -694,9 +748,7 @@
     DigitList digits;
 
     // This detects negativity too.
-    digits.set(number, fUseExponentialNotation ?
-                             getMinimumIntegerDigits() + getMaximumFractionDigits() :
-                             getMaximumFractionDigits(),
+    digits.set(number, precision(FALSE),
                              !fUseExponentialNotation);
 
     return subformat(appendTo, fieldPosition, digits, FALSE);
@@ -792,6 +844,15 @@
     }
     int32_t maxIntDig = getMaximumIntegerDigits();
     int32_t minIntDig = getMinimumIntegerDigits();
+    if (fUseExponentialNotation && maxIntDig > kMaxScientificIntegerDigits) {
+        maxIntDig = 1;
+	    if (maxIntDig < minIntDig) {
+		    maxIntDig = minIntDig;
+	    }
+    }
+    if (fUseExponentialNotation && maxIntDig > minIntDig) {
+        minIntDig = 1;
+    }
 
     /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
      * format as zero.  This allows sensible computations and preserves
@@ -916,8 +977,14 @@
 
         DigitList expDigits;
         expDigits.set(exponent);
-        for (i=expDigits.fDecimalAt; i<fMinExponentDigits; ++i)
-            appendTo += (zero);
+		{
+            int expDig = fMinExponentDigits;
+            if (fUseExponentialNotation && expDig < 1) {
+                expDig = 1;
+            }
+            for (i=expDigits.fDecimalAt; i<expDig; ++i)
+                appendTo += (zero);
+		}
         for (i=0; i<expDigits.fDecimalAt; ++i)
         {
             UChar32 c = (UChar32)((i < expDigits.fCount) ?
@@ -1165,6 +1232,17 @@
             return;
         }
     }
+    else if (digits.fitsIntoInt64(isParseIntegerOnly())) {
+        int64_t n = digits.getInt64();
+        if (n % mult == 0) {
+            result.setInt64(n / mult);
+            return;
+        }
+        else {  // else handle the remainder
+            result.setDouble(((double)n) / mult);
+            return;
+        }
+    }
     else {
         // Handle non-integral or very large values
         // Dividing by one is okay and not that costly.
@@ -1251,7 +1329,6 @@
             decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
         }
         const UnicodeString *grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
-        const UnicodeString *exponentChar = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
         UBool sawDecimal = FALSE;
         UBool sawDigit = FALSE;
         int32_t backup = -1;
@@ -1722,11 +1799,24 @@
 void
 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
 {
-    if (fSymbols != NULL)
+    if (symbolsToAdopt == NULL) {
+        return; // do not allow caller to set fSymbols to NULL
+    }
+
+    UBool sameSymbols = FALSE;
+    if (fSymbols != NULL) {
+        sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
+            symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
+            getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
+            symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
         delete fSymbols;
+    }
 
     fSymbols = symbolsToAdopt;
-    setCurrencyForSymbols();
+    if (!sameSymbols) {
+        // If the currency symbols are the same, there is no need to recalculate.
+        setCurrencyForSymbols();
+    }
     expandAffixes();
 }
 //------------------------------------------------------------------------------
@@ -1759,17 +1849,22 @@
     // currency object to one for that locale.  If it is custom,
     // we set the currency to null.
     UErrorCode ec = U_ZERO_ERROR;
-    DecimalFormatSymbols def(fSymbols->getLocale(), ec);
+    const UChar* c = NULL;
+    const char* loc = fSymbols->getLocale().getName();
+    UChar intlCurrencySymbol[4]; 
+    ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
+    UnicodeString currencySymbol;
 
-    if (getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
-        def.getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
-        getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
-        def.getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)
-    ) {
-        setCurrencyForLocale(fSymbols->getLocale().getName(), ec);
-    } else {
-        setCurrency(NULL); // Use DFS currency info
+    uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
+    if (U_SUCCESS(ec)
+        && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol
+        && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == intlCurrencySymbol)
+    {
+        // Trap an error in mapping locale to currency.  If we can't
+        // map, then don't fail and set the currency to "".
+        c = intlCurrencySymbol;
     }
+    setCurrency(c);
 }
 
 
@@ -2064,9 +2159,6 @@
  */
 void DecimalFormat::setScientificNotation(UBool useScientific) {
     fUseExponentialNotation = useScientific;
-    if (fUseExponentialNotation && fMinExponentDigits < 1) {
-        fMinExponentDigits = 1;
-    }
 }
 
 /**
@@ -2592,9 +2684,15 @@
         if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
             g += fGroupingSize2;
         }
-        int32_t maxIntDig = fUseExponentialNotation ? getMaximumIntegerDigits() :
-          (uprv_max(uprv_max(g, getMinimumIntegerDigits()),
-                   roundingDecimalPos) + 1);
+        int maxIntDig = getMaximumIntegerDigits();
+        if (fUseExponentialNotation) {
+            if (maxIntDig > kMaxScientificIntegerDigits) {
+                maxIntDig = 1;
+            }
+        } else {
+            maxIntDig = uprv_max(uprv_max(g, getMinimumIntegerDigits()),
+                      roundingDecimalPos) + 1;
+        }
         for (i = maxIntDig; i > 0; --i) {
             if (!fUseExponentialNotation && i<maxIntDig &&
                 isGroupingPosition(i)) {
@@ -2840,7 +2938,7 @@
         int8_t groupingCount = -1;
         int8_t groupingCount2 = -1;
         int32_t padPos = -1;
-        UChar32 padChar;
+        UChar32 padChar = 0;
         int32_t roundingPos = -1;
         DigitList roundingInc;
         int8_t expDigits = -1;
@@ -3434,6 +3532,13 @@
 
         expandAffixes();
     }
+}
+
+int32_t
+DecimalFormat::precision(UBool isIntegral) const {
+	return fUseExponentialNotation 
+	    ? getMinimumIntegerDigits() + getMaximumFractionDigits() 
+	    : (isIntegral ? 0 : getMaximumFractionDigits());
 }
 
 U_NAMESPACE_END

Index: dtfmtsym.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/dtfmtsym.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- dtfmtsym.cpp	10 Sep 2003 02:42:22 -0000	1.4
+++ dtfmtsym.cpp	6 Apr 2004 10:08:46 -0000	1.5
@@ -29,6 +29,7 @@
 #include "mutex.h"
 #include "cmemory.h"
 #include "cstring.h"
+#include "locbased.h"
  
 // *****************************************************************************
 // class DateFormatSymbols
@@ -111,25 +112,25 @@
 
 U_NAMESPACE_BEGIN
 
-const char DateFormatSymbols::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
 
 /**
  * These are the tags we expect to see in normal resource bundle files associated
  * with a locale.
  */
-const char DateFormatSymbols::fgErasTag[]="Eras";
-const char DateFormatSymbols::fgMonthNamesTag[]="MonthNames";
-const char DateFormatSymbols::fgMonthAbbreviationsTag[]="MonthAbbreviations";
-const char DateFormatSymbols::fgDayNamesTag[]="DayNames";
-const char DateFormatSymbols::fgDayAbbreviationsTag[]="DayAbbreviations";
-const char DateFormatSymbols::fgAmPmMarkersTag[]="AmPmMarkers";
+const char gErasTag[]="Eras";
+const char gMonthNamesTag[]="MonthNames";
+const char gMonthAbbreviationsTag[]="MonthAbbreviations";
+const char gDayNamesTag[]="DayNames";
+const char gDayAbbreviationsTag[]="DayAbbreviations";
+const char gAmPmMarkersTag[]="AmPmMarkers";
 
 /**
  * These are the tags we expect to see in time zone data resource bundle files
  * associated with a locale.
  */
-const char DateFormatSymbols::fgZoneStringsTag[]="zoneStrings";
-const char DateFormatSymbols::fgLocalPatternCharsTag[]="localPatternChars";
+const char gZoneStringsTag[]="zoneStrings";
+const char gLocalPatternCharsTag[]="localPatternChars";
 
 /**
  * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
@@ -507,7 +508,7 @@
 //------------------------------------------------------
 
 void
-DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const ResourceBundle data, UErrorCode &status) {
+DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const ResourceBundle &data, UErrorCode &status) {
     if (U_SUCCESS(status)) {
         length = data.getSize();
         *field = newUnicodeStringArray(length);
@@ -546,34 +547,36 @@
 ResourceBundle
 DateFormatSymbols::getData(ResourceBundle &rb, const char *tag, const char *type, UErrorCode& status )
 {
-    char tmp[100];
-    char *fullTag = tmp;
-    
-    if(!type || !*type) {
-        type = "gregorian";
-    }
-    
-    int32_t len = uprv_strlen(tag) + 1 + uprv_strlen(type);  // tag + _ + type  (i.e. Eras_Japanese )
-    if(len >= (int32_t)sizeof(tmp)) {
-        fullTag = (char*)uprv_malloc(len+1);
-    }
-    
-    uprv_strcpy(fullTag, tag);
-    uprv_strcat(fullTag, "_");
-    uprv_strcat(fullTag, type);
-    
-    ResourceBundle resource = rb.get(fullTag, status);
-    
-    if(status == U_MISSING_RESOURCE_ERROR) {
-        status = U_ZERO_ERROR;
-        resource = rb.get(tag, status);
-    }
-    
-    if(fullTag != tmp) {  
-        uprv_free(fullTag);  // not stack allocated
+    if(type && *type && (uprv_strcmp(type, "gregorian") != 0)) {
+        char tmp[100];
+        char *fullTag = tmp;
+        int32_t len = uprv_strlen(tag) + 1 + uprv_strlen(type);  // tag + _ + type  (i.e. Eras_Japanese )
+
+        if(len >= (int32_t)sizeof(tmp)) {
+            fullTag = (char*)uprv_malloc(len+1);
+        }
+
+        uprv_strcpy(fullTag, tag);
+        uprv_strcat(fullTag, "_");
+        uprv_strcat(fullTag, type);
+
+        ResourceBundle resource(rb.get(fullTag, status));
+
+        if(fullTag != tmp) {  
+            uprv_free(fullTag);  // not stack allocated
+        }
+
+        // fallback if not found
+        if(status == U_MISSING_RESOURCE_ERROR) {
+            status = U_ZERO_ERROR;
+            resource = rb.get(tag, status);
+        }
+
+        return resource;
+    } else {
+        // Gregorian case
+        return rb.get(tag, status);
     }
-    
-    return resource;
 }
 
 void
@@ -641,17 +644,21 @@
 
     // if we make it to here, the resource data is cool, and we can get everything out
     // of it that we need except for the time-zone and localized-pattern data, which
-    // are stoerd in a separate file
-    initField(&fEras, fErasCount, getData(resource, fgErasTag, type, status), status);
-    initField(&fMonths, fMonthsCount, getData(resource, fgMonthNamesTag, type, status), status);
-    initField(&fShortMonths, fShortMonthsCount, getData(resource, fgMonthAbbreviationsTag, type, status), status);
-    initField(&fAmPms, fAmPmsCount, getData(resource, fgAmPmMarkersTag, type, status), status);
+    // are stored in a separate file
+    ResourceBundle data = getData(resource, gErasTag, type, status);
+    U_LOCALE_BASED(locBased, *this);
+    locBased.setLocaleIDs(data.getLocale(ULOC_VALID_LOCALE, status).getName(),
+                          data.getLocale(ULOC_ACTUAL_LOCALE, status).getName());
+    initField(&fEras, fErasCount, data, status);
+    initField(&fMonths, fMonthsCount, getData(resource, gMonthNamesTag, type, status), status);
+    initField(&fShortMonths, fShortMonthsCount, getData(resource, gMonthAbbreviationsTag, type, status), status);
+    initField(&fAmPms, fAmPmsCount, getData(resource, gAmPmMarkersTag, type, status), status);
     // fastCopyFrom() - see assignArray comments
-    fLocalPatternChars.fastCopyFrom(resource.getStringEx(fgLocalPatternCharsTag, status));
+    fLocalPatternChars.fastCopyFrom(resource.getStringEx(gLocalPatternCharsTag, status));
 
-    ResourceBundle zoneArray = resource.get(fgZoneStringsTag, status);
+    ResourceBundle zoneArray(resource.get(gZoneStringsTag, status));
     fZoneStringsRowCount = zoneArray.getSize();
-    ResourceBundle zoneRow = zoneArray.get((int32_t)0, status);
+    ResourceBundle zoneRow(zoneArray.get((int32_t)0, status));
     /* TODO: Fix the case where the zoneStrings is not a perfect square array of information. */
     fZoneStringsColCount = zoneRow.getSize();
     fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
@@ -675,7 +682,7 @@
     }
 
     // {sfb} fixed to handle 1-based weekdays
-    ResourceBundle weekdaysData = getData(resource, fgDayNamesTag, type, status);
+    ResourceBundle weekdaysData(getData(resource, gDayNamesTag, type, status));
     fWeekdaysCount = weekdaysData.getSize();
     fWeekdays = new UnicodeString[fWeekdaysCount+1];
     /* test for NULL */
@@ -688,8 +695,9 @@
         // fastCopyFrom() - see assignArray comments
         fWeekdays[i+1].fastCopyFrom(weekdaysData.getStringEx(i, status));
     }
+    fWeekdaysCount++;
 
-    ResourceBundle lsweekdaysData = getData(resource, fgDayAbbreviationsTag, type, status);
+    ResourceBundle lsweekdaysData(getData(resource, gDayAbbreviationsTag, type, status));
     fShortWeekdaysCount = lsweekdaysData.getSize();
     fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
     /* test for NULL */
@@ -702,9 +710,8 @@
         // fastCopyFrom() - see assignArray comments
         fShortWeekdays[i+1].fastCopyFrom(lsweekdaysData.getStringEx(i, status));
     }
+    fShortWeekdaysCount++;
 
-    fWeekdaysCount = fShortWeekdaysCount = 8;
-    
     // If the locale data does not include new pattern chars, use the defaults
     if (fLocalPatternChars.length() < PATTERN_CHARS_LEN) {
         fLocalPatternChars.append(&gPatternChars[fLocalPatternChars.length()]);
@@ -758,6 +765,12 @@
     }
 
     return -1;
+}
+
+Locale 
+DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
+    U_LOCALE_BASED(locBased, *this);
+    return locBased.getLocale(type, status);
 }
 
 U_NAMESPACE_END

Index: esctrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/esctrn.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- esctrn.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ esctrn.cpp	6 Apr 2004 10:08:46 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -27,7 +27,7 @@
 static const UChar RBRACE[] = {125,0}; // "}"
 static const UChar EMPTY[] = {0}; // ""
 
-const char EscapeTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EscapeTransliterator)
 
 /**
  * Factory methods
@@ -127,8 +127,11 @@
 /**
  * Implements {@link Transliterator#handleTransliterate}.
  */
-void EscapeTransliterator::handleTransliterate(Replaceable& text, UTransPosition& pos,
-                                               UBool isIncremental) const {
+void EscapeTransliterator::handleTransliterate(Replaceable& text,
+                                               UTransPosition& pos,
+                                               UBool /*isIncremental*/) const
+{
+    /* TODO: Verify that isIncremental can be ignored */
     int32_t start = pos.start;
     int32_t limit = pos.limit;
 

Index: esctrn.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/esctrn.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- esctrn.h	10 Sep 2003 02:42:22 -0000	1.3
+++ esctrn.h	6 Apr 2004 10:08:46 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001-2002, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -82,12 +82,6 @@
      */
     EscapeTransliterator* supplementalHandler;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
  public:
 
     /**
@@ -126,14 +120,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 

Index: fmtable.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/fmtable.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- fmtable.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ fmtable.cpp	6 Apr 2004 10:08:46 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 1997-2001, International Business Machines Corporation and    *
+* Copyright (C) 1997-2003, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
@@ -26,7 +26,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char Formattable::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
 
 // -------------------------------------
 // default constructor.
@@ -35,7 +35,7 @@
 Formattable::Formattable()
     :   UObject(), fType(kLong)
 {
-    fValue.fLong = 0;
+    fValue.fInt64 = 0;
 }
 
 // -------------------------------------
@@ -44,6 +44,7 @@
 Formattable::Formattable(UDate date, ISDATE /*isDate*/)
     :   UObject(), fType(kDate)
 {
+    fBogus.setToBogus();
     fValue.fDate = date;
 }
 
@@ -53,6 +54,7 @@
 Formattable::Formattable(double value)
     :   UObject(), fType(kDouble)
 {
+    fBogus.setToBogus();
     fValue.fDouble = value;
 }
 
@@ -62,7 +64,18 @@
 Formattable::Formattable(int32_t value)
     :   UObject(), fType(kLong)
 {
-    fValue.fLong = value;
+    fBogus.setToBogus();
+    fValue.fInt64 = value;
+}
+
+// -------------------------------------
+// Creates a formattable object with a long value.
+
+Formattable::Formattable(int64_t value)
+    :   UObject(), fType(kInt64)
+{
+    fBogus.setToBogus();
+    fValue.fInt64 = value;
 }
 
 // -------------------------------------
@@ -71,6 +84,7 @@
 Formattable::Formattable(const char* stringToCopy)
     :   UObject(), fType(kString)
 {
+    fBogus.setToBogus();
     fValue.fString = new UnicodeString(stringToCopy);
 }
 
@@ -80,6 +94,7 @@
 Formattable::Formattable(const UnicodeString& stringToCopy)
     :   UObject(), fType(kString)
 {
+    fBogus.setToBogus();
     fValue.fString = new UnicodeString(stringToCopy);
 }
 
@@ -90,6 +105,7 @@
 Formattable::Formattable(UnicodeString* stringToAdopt)
     :   UObject(), fType(kString)
 {
+    fBogus.setToBogus();
     fValue.fString = stringToAdopt;
 }
 
@@ -98,6 +114,7 @@
 Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
     :   UObject(), fType(kArray)
 {
+    fBogus.setToBogus();
     fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
     fValue.fArrayAndCount.fCount = count;
 }
@@ -108,6 +125,7 @@
 Formattable::Formattable(const Formattable &source)
     :   UObject(source), fType(kLong)
 {
+    fBogus.setToBogus();
     *this = source;
 }
 
@@ -141,8 +159,9 @@
             fValue.fDouble = source.fValue.fDouble;
             break;
         case kLong:
+        case kInt64:
             // Sets the long value.
-            fValue.fLong = source.fValue.fLong;
+            fValue.fInt64 = source.fValue.fInt64;
             break;
         case kDate:
             // Sets the Date value.
@@ -171,7 +190,8 @@
     case kDouble:
         return fValue.fDouble == that.fValue.fDouble;
     case kLong:
-        return fValue.fLong == that.fValue.fLong;
+        case kInt64:
+        return fValue.fInt64 == that.fValue.fInt64;
     case kString:
         return *(fValue.fString) == *(that.fValue.fString);
     case kArray:
@@ -208,10 +228,16 @@
     case kDate:
     case kDouble:
     case kLong:
+    case kInt64:
         break;
     }
 }
 
+Formattable *
+Formattable::clone() const {
+    return new Formattable(*this);
+}
+
 // -------------------------------------
 // Gets the data type of this Formattable object. 
 Formattable::Type
@@ -221,6 +247,88 @@
 }
 
 // -------------------------------------
+int32_t
+Formattable::getLong(UErrorCode* status) const
+{
+    if(U_FAILURE(*status))
+        return 0;
+        
+    switch (fType) {
+    case Formattable::kLong: 
+        return (int32_t)fValue.fInt64;
+    case Formattable::kInt64: 
+        if (fValue.fInt64 > INT32_MAX) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return INT32_MAX;
+        } else if (fValue.fInt64 < INT32_MIN) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return INT32_MIN;
+        } else {
+            return (int32_t)fValue.fInt64;
+        }
+    case Formattable::kDouble:
+        if (fValue.fDouble > INT32_MAX) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return INT32_MAX;
+        } else if (fValue.fDouble < INT32_MIN) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return INT32_MIN;
+        } else {
+            return (int32_t)fValue.fDouble;
+        }
+    default: 
+        *status = U_INVALID_FORMAT_ERROR;
+        return 0;
+    }
+}
+
+// -------------------------------------
+int64_t
+Formattable::getInt64(UErrorCode* status) const
+{
+    if(U_FAILURE(*status))
+        return 0;
+        
+    switch (fType) {
+    case Formattable::kLong: 
+    case Formattable::kInt64: 
+        return fValue.fInt64;
+    case Formattable::kDouble:
+        if (fValue.fDouble > U_INT64_MAX) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return U_INT64_MAX;
+        } else if (fValue.fDouble < U_INT64_MIN) {
+            *status = U_INVALID_FORMAT_ERROR;
+            return U_INT64_MIN;
+        } else {
+            return (int64_t)fValue.fDouble;
+        }
+    default: 
+        *status = U_INVALID_FORMAT_ERROR;
+        return 0;
+    }
+}
+
+// -------------------------------------
+double
+Formattable::getDouble(UErrorCode* status) const
+{
+    if(U_FAILURE(*status))
+        return 0;
+        
+    switch (fType) {
+    case Formattable::kLong: 
+    case Formattable::kInt64: // loses precision
+        return (double)fValue.fInt64;
+    case Formattable::kDouble:
+        return fValue.fDouble;
+    default: 
+        *status = U_INVALID_FORMAT_ERROR;
+        return 0;
+    }
+}
+
+// -------------------------------------
 // Sets the value to a double value d.
 
 void
@@ -239,7 +347,18 @@
 {
     dispose();
     fType = kLong;
-    fValue.fLong = l;
+    fValue.fInt64 = l;
+}
+
+// -------------------------------------
+// Sets the value to an int64 value ll.
+
+void
+Formattable::setInt64(int64_t ll)
+{
+    dispose();
+    fType = kInt64;
+    fValue.fInt64 = ll;
 }
 
 // -------------------------------------
@@ -297,6 +416,63 @@
     fType = kArray;
     fValue.fArrayAndCount.fArray = array;
     fValue.fArrayAndCount.fCount = count;
+}
+
+// -------------------------------------
+UnicodeString& 
+Formattable::getString(UnicodeString& result, UErrorCode* status) const 
+{
+    if (status && U_SUCCESS(*status) && fType != kString) {
+        *status = U_INVALID_FORMAT_ERROR;
+        result.setToBogus();
+    } else {
+        result = *fValue.fString;
+    }
+    return result;
+}
+
+// -------------------------------------
+const UnicodeString& 
+Formattable::getString(UErrorCode* status) const 
+{
+    if (status && U_SUCCESS(*status) && fType != kString) {
+        *status = U_INVALID_FORMAT_ERROR;
+        return *getBogus();
+    }
+    return *fValue.fString;
+}
+
+// -------------------------------------
+UnicodeString& 
+Formattable::getString(UErrorCode* status) 
+{
+    if (status && U_SUCCESS(*status) && fType != kString) {
+        *status = U_INVALID_FORMAT_ERROR;
+        return *getBogus();
+    }
+    return *fValue.fString;
+}
+
+// -------------------------------------
+const Formattable* 
+Formattable::getArray(int32_t& count, UErrorCode* status) const 
+{
+    if (status && U_SUCCESS(*status) && fType != kArray) {
+        count = 0;
+        *status = U_INVALID_FORMAT_ERROR;
+        return NULL;
+    }
+    count = fValue.fArrayAndCount.fCount; 
+    return fValue.fArrayAndCount.fArray;
+}
+
+// -------------------------------------
+// Gets the bogus string, ensures mondo bogosity.
+
+UnicodeString*
+Formattable::getBogus() const 
+{
+    return (UnicodeString*)&fBogus; /* cast away const :-( */
 }
 
 #if 0

Index: format.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/format.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- format.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ format.cpp	6 Apr 2004 10:08:47 -0000	1.4
@@ -39,6 +39,9 @@
 #if !UCONFIG_NO_FORMATTING
 
 #include "unicode/format.h"
+#include "unicode/resbund.h"
+#include "cstring.h"
+#include "locbased.h"
 
 // *****************************************************************************
 // class Format
@@ -46,7 +49,14 @@
 
 U_NAMESPACE_BEGIN
 
-const char FieldPosition::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FieldPosition)
+
+FieldPosition::~FieldPosition() {}
+
+FieldPosition *
+FieldPosition::clone() const {
+    return new FieldPosition(*this);
+}
 
 // -------------------------------------
 // default constructor
@@ -54,6 +64,7 @@
 Format::Format()
     : UObject()
 {
+    *validLocale = *actualLocale = 0;
 }
 
 // -------------------------------------
@@ -68,14 +79,17 @@
 Format::Format(const Format &that)
     : UObject(that)
 {
+    *this = that;
 }
 
 // -------------------------------------
 // assignment operator
 
 Format&
-Format::operator=(const Format& /*that*/)
+Format::operator=(const Format& that)
 {
+    uprv_strcpy(validLocale, that.validLocale);
+    uprv_strcpy(actualLocale, that.actualLocale);
     return *this;
 }
 
@@ -154,6 +168,31 @@
     pattern.extract(start,stop-start,parseError.postContext,0);
     //null terminate the buffer
     parseError.postContext[stop-start]= 0;
+}
+
+Locale 
+Format::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
+    U_LOCALE_BASED(locBased, *this);
+    return locBased.getLocale(type, status);
+}
+
+const char *
+Format::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const {
+    U_LOCALE_BASED(locBased, *this);
+    return locBased.getLocaleID(type, status);
+}
+
+void
+Format::setLocales(const ResourceBundle& res) {
+    UErrorCode status = U_ZERO_ERROR;
+    setLocaleIDs(res.getLocale(ULOC_VALID_LOCALE, status).getName(),
+                 res.getLocale(ULOC_ACTUAL_LOCALE, status).getName());
+}
+
+void
+Format::setLocaleIDs(const char* valid, const char* actual) {
+    U_LOCALE_BASED(locBased, *this);
+    locBased.setLocaleIDs(valid, actual);
 }
 
 U_NAMESPACE_END

Index: funcrepl.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/funcrepl.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- funcrepl.cpp	10 Sep 2003 02:42:22 -0000	1.1
+++ funcrepl.cpp	6 Apr 2004 10:08:47 -0000	1.2
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002, International Business Machines Corporation
+*   Copyright (c) 2002-2003, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -22,7 +22,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char FunctionReplacer::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FunctionReplacer)
 
 /**
  * Construct a replacer that takes the output of the given
@@ -38,7 +38,10 @@
 /**
  * Copy constructor.
  */
-FunctionReplacer::FunctionReplacer(const FunctionReplacer& other) {
+FunctionReplacer::FunctionReplacer(const FunctionReplacer& other) :
+    UnicodeFunctor(other),
+    UnicodeReplacer(other)
+{
     translit = other.translit->clone();
     replacer = other.replacer->clone();
 }

Index: funcrepl.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/funcrepl.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- funcrepl.h	10 Sep 2003 02:42:22 -0000	1.1
+++ funcrepl.h	6 Apr 2004 10:08:47 -0000	1.2
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002, International Business Machines Corporation
+*   Copyright (c) 2002-2003, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -45,12 +45,6 @@
      */
     UnicodeFunctor* replacer;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
  public:
 
     /**
@@ -111,14 +105,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 };
 
 U_NAMESPACE_END

Index: gregocal.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/gregocal.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gregocal.cpp	10 Sep 2003 02:42:22 -0000	1.3
+++ gregocal.cpp	6 Apr 2004 10:08:47 -0000	1.4
@@ -43,25 +43,19 @@
 #if !UCONFIG_NO_FORMATTING
 
 #include "unicode/gregocal.h"
-#include "unicode/smpdtfmt.h"  /* for the public field (!) SimpleDateFormat::fgSystemDefaultCentury */
+#include "gregoimp.h"
 #include "mutex.h"
-
+#include "uassert.h"
 
 // *****************************************************************************
 // class GregorianCalendar
[...2412 lines suppressed...]
     Mutex m;
-    needsUpdate = (fgSystemDefaultCenturyStart == SimpleDateFormat::fgSystemDefaultCentury);
+    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
   }
 
   if (needsUpdate) {
@@ -2159,7 +1300,7 @@
   // on the current time.  They'll be set to 80 years before
   // the current time.
   // No point in locking as it should be idempotent.
-  if (fgSystemDefaultCenturyStart == SimpleDateFormat::fgSystemDefaultCentury)
+  if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
   {
     UErrorCode status = U_ZERO_ERROR;
     Calendar *calendar = new GregorianCalendar(status);
@@ -2188,4 +1329,3 @@
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof
-

Index: hextouni.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/hextouni.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- hextouni.cpp	10 Sep 2003 02:42:22 -0000	1.4
+++ hextouni.cpp	6 Apr 2004 10:08:47 -0000	1.5
@@ -20,12 +20,12 @@
 
 U_NAMESPACE_BEGIN
 
-const char HexToUnicodeTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(HexToUnicodeTransliterator)
 
 /**
  * ID for this transliterator.
  */
-const char HexToUnicodeTransliterator::_ID[] = "Hex-Any";
+const char CURR_ID[] = "Hex-Any";
 
 /**
  * This pattern encodes the following specs for the default constructor:
@@ -36,7 +36,7 @@
  * The multiple backslashes resolve to a single backslash
  * in the effective prefix.
  */
-const UChar HexToUnicodeTransliterator::DEFAULT_PATTERN[] = {
+static const UChar DEFAULT_PATTERN[] = {
     0x5C, 0x5C, 0x75, 0x30, 0x30, 0x30, 0x30, 0x3B,  /* "\\u0000;" */
     0x5C, 0x5C, 0x55, 0x30, 0x30, 0x30, 0x30, 0x3B,  /* "\\U0000;" */
     0x75, 0x2B, 0x30, 0x30, 0x30, 0x30, 0x3B,        /* "u+0000;" */
@@ -47,11 +47,13 @@
     0x41, 0x41, 0x41, 0x41, 0
 };  /* "AAAA" */
 
+HexToUnicodeTransliterator::~HexToUnicodeTransliterator() {}
+
 /**
  * Constructs a transliterator.
  */
 HexToUnicodeTransliterator::HexToUnicodeTransliterator(UnicodeFilter* adoptedFilter) :
-    Transliterator(_ID, adoptedFilter) {
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter) {
     // We don't need to pass the status back to the caller because
     // we know that the DEFAULT_PATTERN parses.
     UErrorCode status = U_ZERO_ERROR;
@@ -63,7 +65,7 @@
  */
 HexToUnicodeTransliterator::HexToUnicodeTransliterator(const UnicodeString& thePattern,
                                                        UErrorCode& status) :
-    Transliterator(_ID, 0) {
+    Transliterator(UnicodeString(CURR_ID, ""), 0) {
     applyPattern(thePattern, status);
 }
 
@@ -73,7 +75,7 @@
 HexToUnicodeTransliterator::HexToUnicodeTransliterator(const UnicodeString& thePattern,
                                                        UnicodeFilter* adoptedFilter,
                                                        UErrorCode& status) :
-    Transliterator(_ID, adoptedFilter) {
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter) {
     applyPattern(thePattern, status);
 }
 

Index: hextouni.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/hextouni.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- hextouni.h	10 Sep 2003 02:42:22 -0000	1.1
+++ hextouni.h	6 Apr 2004 10:08:47 -0000	1.2
@@ -32,15 +32,6 @@
  */
 class U_I18N_API HexToUnicodeTransliterator : public Transliterator {
 
-    /**
-     * ID for this transliterator.
-     */
-    static const char _ID[];
-
-    /**
-     * The pattern used by the default constructor
-     */
-    static const UChar DEFAULT_PATTERN[];
 
     // Character constants defined here to avoid ASCII dependency
     enum {
@@ -66,12 +57,6 @@
      */
     int32_t affixCount;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
 public:
 
     /**
@@ -171,25 +156,15 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const;
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID();
+    static UClassID getStaticClassID();
 };
-
-inline HexToUnicodeTransliterator::~HexToUnicodeTransliterator() {}
-
-inline UClassID
-HexToUnicodeTransliterator::getStaticClassID()
-{ return (UClassID)&fgClassID; }
-
-inline UClassID
-HexToUnicodeTransliterator::getDynamicClassID() const
-{ return HexToUnicodeTransliterator::getStaticClassID(); }
 
 U_NAMESPACE_END
 

Index: i18n.dsp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/i18n.dsp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- i18n.dsp	10 Sep 2003 02:42:22 -0000	1.5
+++ i18n.dsp	6 Apr 2004 10:08:47 -0000	1.6
@@ -55,7 +55,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 icuuc.lib /nologo /base:"0x4a900000" /dll /machine:I386 /out:"..\..\bin\icuin26.dll" /implib:"..\..\lib\icuin.lib" /libpath:"..\..\lib"
+# ADD LINK32 icuuc.lib /nologo /base:"0x4a900000" /dll /machine:I386 /out:"..\..\bin\icuin28.dll" /implib:"..\..\lib\icuin.lib" /libpath:"..\..\lib"
 # SUBTRACT LINK32 /pdb:none /debug
 
 !ELSEIF  "$(CFG)" == "i18n - Win32 Debug"
@@ -82,7 +82,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 icuucd.lib /nologo /base:"0x4a900000" /dll /debug /machine:I386 /out:"..\..\bin\icuin26d.dll" /implib:"..\..\lib\icuind.lib" /pdbtype:sept /libpath:"..\..\lib"
+# ADD LINK32 icuucd.lib /nologo /base:"0x4a900000" /dll /debug /machine:I386 /out:"..\..\bin\icuin28d.dll" /implib:"..\..\lib\icuind.lib" /pdbtype:sept /libpath:"..\..\lib"
 # SUBTRACT LINK32 /pdb:none
 
 !ELSEIF  "$(CFG)" == "i18n - Win64 Release"
@@ -109,7 +109,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:IX86 /machine:IA64
-# ADD LINK32 icuuc.lib /nologo /base:"0x4a900000" /dll /machine:IX86 /out:"..\..\bin\icuin26.dll" /implib:"..\..\lib\icuin.lib" /libpath:"..\..\lib" /machine:IA64
+# ADD LINK32 icuuc.lib /nologo /base:"0x4a900000" /dll /machine:IX86 /out:"..\..\bin\icuin28.dll" /implib:"..\..\lib\icuin.lib" /libpath:"..\..\lib" /machine:IA64
 # SUBTRACT LINK32 /debug
 
 !ELSEIF  "$(CFG)" == "i18n - Win64 Debug"
@@ -136,7 +136,7 @@
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:IX86 /pdbtype:sept /machine:IA64
-# ADD LINK32 icuucd.lib /nologo /base:"0x4a900000" /dll /incremental:no /debug /machine:IX86 /out:"..\..\bin\icuin26d.dll" /implib:"..\..\lib\icuind.lib" /pdbtype:sept /libpath:"..\..\lib" /machine:IA64
+# ADD LINK32 icuucd.lib /nologo /base:"0x4a900000" /dll /incremental:no /debug /machine:IX86 /out:"..\..\bin\icuin28d.dll" /implib:"..\..\lib\icuind.lib" /pdbtype:sept /libpath:"..\..\lib" /machine:IA64
 
 !ENDIF 
 
@@ -678,10 +678,42 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\islamcal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\islamcal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\astro.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\astro.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\calendar.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\chnsecal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\chnsecal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hebrwcal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hebrwcal.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\unicode\calendar.h
 
 !IF  "$(CFG)" == "i18n - Win32 Release"
@@ -933,6 +965,14 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\digitlst.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\digitlst.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\dtfmtsym.cpp
 # End Source File
 # Begin Source File
@@ -1184,6 +1224,14 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\gregoimp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\gregoimp.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\japancal.cpp
 # End Source File
 # Begin Source File
@@ -1322,6 +1370,14 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\olsontz.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\olsontz.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\rbnf.cpp
 # End Source File
 # Begin Source File
@@ -1526,10 +1582,6 @@
 # End Source File
 # Begin Source File
 
-SOURCE=.\tzdat.h
-# End Source File
-# Begin Source File
-
 SOURCE=.\ucal.cpp
 # End Source File
 # Begin Source File
@@ -1632,6 +1684,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\ucurrimp.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\udat.cpp
 # End Source File
 # Begin Source File
@@ -1886,10 +1942,6 @@
 # End Source File
 # Begin Source File
 
-SOURCE=.\remtrans.cpp
-# End Source File
-# Begin Source File
-
 SOURCE=.\repattrn.cpp
 # End Source File
 # End Group
@@ -2010,6 +2062,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\remtrans.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\remtrans.h
 # End Source File
 # Begin Source File
@@ -2284,6 +2340,37 @@
 	copy    $(InputPath)    ..\..\include\unicode
 
 # End Custom Build
+
+!ENDIF 
+
+# End Source File
+# End Group
+# Begin Group "locale"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ulocdata.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unicode\ulocdata.h
+
+!IF  "$(CFG)" == "i18n - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "i18n - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\unicode\ulocdata.h
+
+"..\..\include\unicode\ulocdata.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+	copy    $(InputPath)    ..\..\include\unicode
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "i18n - Win64 Release"
+
+!ELSEIF  "$(CFG)" == "i18n - Win64 Debug"
 
 !ENDIF 
 

Index: i18n.rc
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/i18n.rc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- i18n.rc	10 Sep 2003 02:42:23 -0000	1.3
+++ i18n.rc	6 Apr 2004 10:08:47 -0000	1.4
@@ -1,29 +1,50 @@
-// Version Resource file for ICU I18N library.
-
 // Do not edit with Microsoft Developer Studio Resource Editor.
 //   It will permanently substitute version numbers that are intended to be
 //   picked up by the pre-processor during each build.
 // Copyright (c) 2001-2003 International Business Machines
 // Corporation and others. All Rights Reserved.
 //
+#include "../common/msvcres.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
 //
 // Generated from the TEXTINCLUDE 2 resource.
 //
-#include "winresrc.h"
-
+#include <winresrc.h>
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
-//
+// 
 
 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
 #pragma code_page(1252)
 
-#include "unicode\uversion.h"
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "../common/msvcres.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include <winresrc.h>\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -59,7 +80,6 @@
 #else
             VALUE "OriginalFilename", "icuin" U_ICU_VERSION_SHORT ".dll\0")
 #endif
-
             VALUE "PrivateBuild", "\0"
             VALUE "ProductName", "International Components for Unicode\0"
             VALUE "ProductVersion", CommaVersionString(U_ICU_VERSION_MAJOR_NUM, U_ICU_VERSION_MINOR_NUM, U_ICU_VERSION_PATCHLEVEL_NUM, 0)
@@ -73,4 +93,16 @@
 END
 
 /////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
 

Index: i18n.vcproj
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/i18n.vcproj,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- i18n.vcproj	10 Sep 2003 02:42:23 -0000	1.1
+++ i18n.vcproj	6 Apr 2004 10:08:47 -0000	1.2
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
+<?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="7.00"
+	Version="7.10"
 	Name="i18n"
 	SccProjectName=""
 	SccLocalPath="">
@@ -23,8 +23,8 @@
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="TRUE"
 				ImproveFloatingPointConsistency="TRUE"
-				AdditionalIncludeDirectories="..\..\include,..\..\source\common"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;I18N_EXPORTS;U_I18N_IMPLEMENTATION"
+				AdditionalIncludeDirectories="..\..\include,..\common"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;U_I18N_IMPLEMENTATION"
 				StringPooling="TRUE"
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="TRUE"
@@ -44,11 +44,11 @@
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
 				AdditionalDependencies="icuuc.lib"
-				OutputFile="..\..\bin\icuin26.dll"
+				OutputFile="..\..\bin\icuin28.dll"
 				LinkIncremental="1"
 				SuppressStartupBanner="TRUE"
 				AdditionalLibraryDirectories="..\..\lib"
-				ProgramDatabaseFile=".\..\..\lib/icuin26.pdb"
+				ProgramDatabaseFile=".\..\..\lib/icuin28.pdb"
 				BaseAddress="0x4a900000"
 				ImportLibrary="..\..\lib\icuin.lib"/>
 			<Tool
@@ -72,7 +72,13 @@
 			<Tool
 				Name="VCWebServiceProxyGeneratorTool"/>
 			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
 				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
 		</Configuration>
 		<Configuration
 			Name="Debug|Win32"
@@ -87,8 +93,8 @@
 				Optimization="0"
 				ImproveFloatingPointConsistency="TRUE"
 				OptimizeForProcessor="2"
-				AdditionalIncludeDirectories="..\..\include,..\..\source\common"
-				PreprocessorDefinitions="_WINDOWS;_USRDLL;I18N_EXPORTS;U_I18N_IMPLEMENTATION;WIN32;_DEBUG;UDATA_MAP"
+				AdditionalIncludeDirectories="..\..\include,..\common"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;U_I18N_IMPLEMENTATION"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
 				DisableLanguageExtensions="TRUE"
@@ -107,12 +113,12 @@
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
 				AdditionalDependencies="icuucd.lib"
-				OutputFile="..\..\bin\icuin26d.dll"
+				OutputFile="..\..\bin\icuin28d.dll"
 				LinkIncremental="2"
 				SuppressStartupBanner="TRUE"
 				AdditionalLibraryDirectories="..\..\lib"
 				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile=".\..\..\lib/icuin26d.pdb"
+				ProgramDatabaseFile=".\..\..\lib/icuin28d.pdb"
 				BaseAddress="0x4a900000"
 				ImportLibrary="..\..\lib\icuind.lib"/>
 			<Tool
@@ -136,9 +142,17 @@
 			<Tool
 				Name="VCWebServiceProxyGeneratorTool"/>
 			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
 				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
 		</Configuration>
 	</Configurations>
+	<References>
+	</References>
 	<Files>
 		<Filter
 			Name="collation"
@@ -158,17 +172,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\coleitr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\coleitr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -180,17 +194,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\coll.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\coll.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -202,17 +216,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\search.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\search.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -224,17 +238,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\sortkey.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\sortkey.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -246,17 +260,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\stsearch.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\stsearch.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -268,17 +282,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\tblcoll.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\tblcoll.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -290,17 +304,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucol.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucol.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -345,17 +359,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucoleitr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucoleitr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -367,17 +381,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\usearch.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\usearch.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -388,6 +402,12 @@
 			Name="formatting"
 			Filter="">
 			<File
+				RelativePath=".\astro.cpp">
+			</File>
+			<File
+				RelativePath=".\astro.h">
+			</File>
+			<File
 				RelativePath=".\buddhcal.cpp">
 			</File>
 			<File
@@ -402,20 +422,26 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\calendar.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\calendar.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\chnsecal.cpp">
+			</File>
+			<File
+				RelativePath=".\chnsecal.h">
+			</File>
+			<File
 				RelativePath=".\choicfmt.cpp">
 			</File>
 			<File
@@ -424,17 +450,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\choicfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\choicfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -446,17 +472,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\datefmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\datefmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -468,17 +494,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\dcfmtsym.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\dcfmtsym.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -490,20 +516,26 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\decimfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\decimfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\digitlst.cpp">
+			</File>
+			<File
+				RelativePath=".\digitlst.h">
+			</File>
+			<File
 				RelativePath=".\dtfmtsym.cpp">
 			</File>
 			<File
@@ -512,17 +544,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\dtfmtsym.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\dtfmtsym.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -531,17 +563,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\fieldpos.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\fieldpos.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -553,17 +585,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\fmtable.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\fmtable.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -575,17 +607,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\format.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\format.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -597,20 +629,38 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\gregocal.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\gregocal.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\gregoimp.cpp">
+			</File>
+			<File
+				RelativePath=".\gregoimp.h">
+			</File>
+			<File
+				RelativePath=".\hebrwcal.cpp">
+			</File>
+			<File
+				RelativePath=".\hebrwcal.h">
+			</File>
+			<File
+				RelativePath=".\islamcal.cpp">
+			</File>
+			<File
+				RelativePath=".\islamcal.h">
+			</File>
+			<File
 				RelativePath=".\japancal.cpp">
 			</File>
 			<File
@@ -625,17 +675,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\msgfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\msgfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -668,20 +718,26 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\numfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\numfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\olsontz.cpp">
+			</File>
+			<File
+				RelativePath=".\olsontz.h">
+			</File>
+			<File
 				RelativePath=".\rbnf.cpp">
 			</File>
 			<File
@@ -690,17 +746,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\rbnf.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\rbnf.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -712,17 +768,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\simpletz.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\simpletz.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -734,17 +790,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\smpdtfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\smpdtfmt.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -756,23 +812,20 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\timezone.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\timezone.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath=".\tzdat.h">
-			</File>
-			<File
 				RelativePath=".\ucal.cpp">
 			</File>
 			<File
@@ -781,17 +834,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucal.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucal.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -803,20 +856,23 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucurr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\ucurr.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\ucurrimp.h">
+			</File>
+			<File
 				RelativePath=".\udat.cpp">
 			</File>
 			<File
@@ -825,17 +881,39 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\udat.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\udat.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\ulocdata.c">
+			</File>
+			<File
+				RelativePath=".\unicode\ulocdata.h">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
+"
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32">
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
+"
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -847,17 +925,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\umsg.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\umsg.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -872,17 +950,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unum.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unum.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 		</Filter>
@@ -908,17 +986,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\regex.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\regex.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -1075,17 +1153,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\translit.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\translit.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -1121,17 +1199,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unifltlg.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unifltlg.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -1140,17 +1218,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unirepl.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\unirepl.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 			<File
@@ -1168,17 +1246,17 @@
 					Name="Release|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\utrans.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 				<FileConfiguration
 					Name="Debug|Win32">
 					<Tool
 						Name="VCCustomBuildTool"
-						CommandLine="copy    $(InputPath)    ..\..\include\unicode
+						CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode
 "
-						Outputs="..\..\include\unicode\utrans.h"/>
+						Outputs="..\..\include\unicode\$(InputFileName)"/>
 				</FileConfiguration>
 			</File>
 		</Filter>

Index: japancal.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/japancal.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- japancal.cpp	10 Sep 2003 02:42:23 -0000	1.1
+++ japancal.cpp	6 Apr 2004 10:08:47 -0000	1.2
@@ -17,6 +17,7 @@
 
 #include "japancal.h"
 #include "unicode/gregocal.h"
+#include "mutex.h"
 
 //#define U_DEBUG_JCAL
 
@@ -309,48 +310,12 @@
   return "japanese";
 }
 
-
-int32_t
-JapaneseCalendar::getMaximum(UCalendarDateFields field) const
-{
-  if(field == UCAL_ERA) {
-    return kCurrentEra;
-  } else {
-    return GregorianCalendar::getMaximum(field);
-  }
-}
-
-int32_t
-JapaneseCalendar::getLeastMaximum(UCalendarDateFields field) const
-{
-  if(field == UCAL_ERA) {
-    return kCurrentEra;
-  } else {
-    return GregorianCalendar::getLeastMaximum(field);
-  }
-}
-
-int32_t
-JapaneseCalendar::monthLength(int32_t month, int32_t year) const
-{
-  return GregorianCalendar::monthLength(month,year);
-}
-
-
-int32_t
-JapaneseCalendar::monthLength(int32_t month) const
-{
-  UErrorCode status = U_ZERO_ERROR;
-  int32_t year = internalGet(UCAL_YEAR);
-  // ignore era
-  return GregorianCalendar::monthLength(month, getGregorianYear(status));
-}
-
-int32_t JapaneseCalendar::getDefaultMonthInYear() const
+int32_t JapaneseCalendar::getDefaultMonthInYear() 
 {
   UErrorCode status  = U_ZERO_ERROR;
   int32_t era = internalGetEra();
-  int32_t year = getGregorianYear(status);
+  computeFields(status); // slow
+  int32_t year = getGregorianYear();
   // TODO do we assume we can trust 'era'?  What if it is denormalized?
 
   int32_t month = GregorianCalendar::getDefaultMonthInYear();
@@ -362,19 +327,15 @@
     return kEraInfo[era].month-1;
   }
 
-  if(era < kCurrentEra) { 
-    // if we're not in the current era, 
-    //    fail_here;
-  }
-
   return month;
 }
 
-int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month) const
+int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month) 
 {
   UErrorCode status  = U_ZERO_ERROR;
   int32_t era = internalGetEra();
-  int32_t year = getGregorianYear(status);
+  computeFields(status); // slow
+  int32_t year = getGregorianYear();
   int32_t day = GregorianCalendar::getDefaultDayInMonth(month);
   
   if(year == kEraInfo[era].year) {
@@ -389,37 +350,31 @@
 
 int32_t JapaneseCalendar::internalGetEra() const
 {
-    return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : kCurrentEra;  
+  return internalGet(UCAL_ERA, kCurrentEra);
 }
 
-int32_t
-JapaneseCalendar::getGregorianYear(UErrorCode &status)  const
+int32_t JapaneseCalendar::handleGetExtendedYear()
 {
-  int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : 1; // default year = 1
-  int32_t era = kCurrentEra;
-  if (fStamp[UCAL_ERA] != kUnset) {
-    era = internalGet(UCAL_ERA);
+  int32_t year;
+
+  if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR &&
+      newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) {
+    year = internalGet(UCAL_EXTENDED_YEAR, 1);
+  } else {
+    // Subtract one because year starts at 1
+    year = internalGet(UCAL_YEAR) + kEraInfo[internalGet(UCAL_ERA)].year - 1;
   }
+  return year;
   
-  if ((era<0)||(era>kCurrentEra)) {
-      status = U_ILLEGAL_ARGUMENT_ERROR;
-      return 0 ;
-  }
-  return year + kEraInfo[era].year - 1;
 }
 
-void JapaneseCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
+
+void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
 {
-  GregorianCalendar::timeToFields(theTime, quick, status);
-  
-  // these are the gregorian era and year
-  int32_t era = internalGet(UCAL_ERA);
-  int32_t year = internalGet(UCAL_YEAR);
-  if(era == GregorianCalendar::BC) {
-    year = 1 - year;
-  }
+  //Calendar::timeToFields(theTime, quick, status);
+  GregorianCalendar::handleComputeFields(julianDay, status);
+  int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year
 
-  //  grego [e+y] -> e+y
   int32_t low = 0;
   
   // Short circuit for recent years.  Most modern computations will
@@ -512,6 +467,68 @@
   return 0;
 }
 
+static int32_t gJapanCalendarLimits[2][4] = {
+  //    Minimum  Greatest min      Least max   Greatest max
+  {        0,        0, JapaneseCalendar::kCurrentEra, JapaneseCalendar::kCurrentEra }, // ERA
+  {        1,        1,           0,           0 }, // YEAR
+};
+
+static UBool gJapanYearLimitsKnown = FALSE;
+
+int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
+{
+  switch(field) {
+  case UCAL_YEAR:
+    {
+      UBool needCalc = FALSE;
+      { 
+        Mutex m;
+        needCalc = (gJapanYearLimitsKnown == FALSE);
+      }
+      if(needCalc) {
+        int32_t min = kEraInfo[1].year - kEraInfo[0].year;
+        int32_t max = min;
+        for (uint32_t i=2; i<kEraCount; i++) { // counting by year, not field (3's)
+          int32_t d = kEraInfo[i].year - kEraInfo[i-1].year;
+          if (d < min) {
+            min = d;
+          } else if (d > max) {
+            max = d;
+          }
+        }
+        { 
+          Mutex m;
+          if(gJapanYearLimitsKnown==FALSE) {
+            gJapanCalendarLimits[field][UCAL_LEAST_MAXIMUM] = min;
+            gJapanCalendarLimits[field][UCAL_MAXIMUM] = max;
+            gJapanYearLimitsKnown = TRUE;
+          }
+        }
+      }
+      return gJapanCalendarLimits[field][limitType];
+    }
+
+  case UCAL_ERA:
+    return gJapanCalendarLimits[field][limitType];
+
+  case UCAL_EXTENDED_YEAR:  // extended year limits
+    switch(limitType) {
+    case UCAL_LIMIT_GREATEST_MINIMUM:
+    case UCAL_LIMIT_MINIMUM:
+      return kEraInfo[0].year;  /* minimum is 1st era year */
+
+    case UCAL_LIMIT_LEAST_MAXIMUM:
+    case UCAL_LIMIT_MAXIMUM:
+      /* use Gregorian calendar max */
+    default:
+      return GregorianCalendar::handleGetLimit(field,limitType);
+    }
+    break;
+
+  default:
+    return GregorianCalendar::handleGetLimit(field,limitType);
+  }
+}
 
 
 U_NAMESPACE_END

Index: japancal.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/japancal.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- japancal.h	10 Sep 2003 02:42:23 -0000	1.1
+++ japancal.h	6 Apr 2004 10:08:47 -0000	1.2
@@ -99,10 +99,14 @@
      */
     virtual Calendar* clone(void) const;
 
-    
+    /**
+     * Return the extended year defined by the current fields.  In the 
+     * Japanese calendar case, this is equal to the equivalent extended Gregorian year.
+     * @internal
+     */
+    virtual int32_t handleGetExtendedYear();
 
 public:
-
     /**
      * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual
      * override. This method is to implement a simple version of RTTI, since not all C++
@@ -137,21 +141,21 @@
     virtual const char * getType() const;
 
     /**
+     * @return FALSE - no default century in Japanese
      * @internal 
-     * @return TRUE if this calendar has the notion of a default century
      */
     virtual UBool haveDefaultCentury() const;
-    virtual UDate defaultCenturyStart() const;
-    virtual int32_t defaultCenturyStartYear() const;
 
-    /** 
+    /**
+     * Not used - no default century.
      * @internal
-     * API overrides
      */
-    int32_t getMaximum(UCalendarDateFields field) const;
-    int32_t getLeastMaximum(UCalendarDateFields field) const;
-    inline virtual int32_t getMaximum(EDateFields field) const { return getMaximum((UCalendarDateFields)field); }
-    inline virtual int32_t getLeastMaximum(EDateFields field) const { return getLeastMaximum((UCalendarDateFields)field); }
+    virtual UDate defaultCenturyStart() const;
+    /**
+     * Not used - no default century.
+     * @internal
+     */
+    virtual int32_t defaultCenturyStartYear() const;
 
 private:
     JapaneseCalendar(); // default constructor not implemented
@@ -159,37 +163,39 @@
     static const char fgClassID;
 
 protected:
-    virtual int32_t monthLength(int32_t month) const; 
-    virtual int32_t monthLength(int32_t month, int32_t year) const; 
-    int32_t getGregorianYear(UErrorCode& status) const;
+    /** 
+     * Calculate the era for internal computation
+     * @internal
+     */
     virtual int32_t internalGetEra() const;
-    virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
 
     /**
-     * (Overrides Calendar) Converts Calendar's time field values to GMT as
-     * milliseconds. In this case, we have to be concerned with filling in inconsistent
-     * information. For example, if the year and era only are set, need to make sure
-     * month & date are set correctly.  Ex, 'Heisei 1' starts Jan 8th, not Jan 1st.  
-     * Default month and date values will end up giving the wrong Era.
-     *
-     * @param status  Output param set to success/failure code on exit. If any value
-     *                previously set in the time field is invalid, this will be set to
-     *                an error status.
-     * @stable ICU 2.0
+     * Compute fields from the JD
+     * @internal
+     */
+    virtual void handleComputeFields(int32_t julianDay, UErrorCode& status);
+
+    /**
+     * Calculate the limit for a specified type of limit and field
+     * @internal
      */
+    virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
 
     /***
      * Called by computeJulianDay.  Returns the default month (0-based) for the year,
-     * taking year and era into account.  Defaults to 0 for Gregorian, which doesn't care.
+     * taking year and era into account.  Will return the first month of the given era, if 
+     * the current year is an ascension year.
+     * @internal
      */
-    virtual int32_t getDefaultMonthInYear() const;
-
+    virtual int32_t getDefaultMonthInYear();
 
     /***
      * Called by computeJulianDay.  Returns the default day (1-based) for the month,
-     * taking currently-set year and era into account.  Defaults to 1 for Gregorian, which doesn't care. 
+     * taking currently-set year and era into account.  Will return the first day of the given
+     * era, if the current month is an ascension year and month.
+     * @internal
      */
-    virtual int32_t getDefaultDayInMonth(int32_t month) const;
+    virtual int32_t getDefaultDayInMonth(int32_t month);
 };
 
 inline UClassID
@@ -205,6 +211,6 @@
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
-#endif // _GREGOCAL
+#endif
 //eof
 

Index: msgfmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/msgfmt.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- msgfmt.cpp	10 Sep 2003 02:42:23 -0000	1.4
+++ msgfmt.cpp	6 Apr 2004 10:08:47 -0000	1.5
@@ -126,7 +126,7 @@
 U_NAMESPACE_BEGIN
 
 // -------------------------------------
-const char MessageFormat::fgClassID = 0; // Value is irrelevant
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MessageFormat)
 
 //--------------------------------------------------------------------
 
@@ -187,6 +187,7 @@
         return;
     }
     applyPattern(pattern, success);
+    setLocaleIDs(fLocale.getName(), fLocale.getName());
 }
  
 MessageFormat::MessageFormat(const UnicodeString& pattern,
@@ -210,6 +211,7 @@
         return;
     }
     applyPattern(pattern, success);
+    setLocaleIDs(fLocale.getName(), fLocale.getName());
 }
 
 MessageFormat::MessageFormat(const UnicodeString& pattern,
@@ -234,6 +236,7 @@
         return;
     }
     applyPattern(pattern, parseError, success);
+    setLocaleIDs(fLocale.getName(), fLocale.getName());
 }
 
 MessageFormat::MessageFormat(const MessageFormat& that)
@@ -427,6 +430,7 @@
         defaultDateFormat = NULL;
     }
     fLocale = theLocale;
+    setLocaleIDs(fLocale.getName(), fLocale.getName());
 }
  
 // -------------------------------------
@@ -975,15 +979,20 @@
             }
         }
         // If the obj data type is a number, use a NumberFormat instance.
-        else if ((type == Formattable::kDouble) || (type == Formattable::kLong)) {
+        else if ((type == Formattable::kDouble) || 
+                 (type == Formattable::kLong) ||
+                 (type == Formattable::kInt64)) {
+
             const NumberFormat* nf = getDefaultNumberFormat(success);
             if (nf == NULL) { 
                 return appendTo; 
             }
             if (type == Formattable::kDouble) {
                 nf->format(obj->getDouble(), appendTo);
-            } else {
+            } else if (type == Formattable::kLong) {
                 nf->format(obj->getLong(), appendTo);
+            } else {
+                nf->format(obj->getInt64(), appendTo);
             }
         }
         // If the obj data type is a Date instance, use a DateFormat instance.

Index: name2uni.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/name2uni.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- name2uni.cpp	10 Sep 2003 02:42:23 -0000	1.4
+++ name2uni.cpp	6 Apr 2004 10:08:48 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -22,9 +22,9 @@
 
 U_NAMESPACE_BEGIN
 
-const char NameUnicodeTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NameUnicodeTransliterator)
 
-const char NameUnicodeTransliterator::_ID[] = "Name-Any";
+const char CURR_ID[] = "Name-Any";
 
 static const UChar OPEN[] = {92,78,126,123,126,0}; // "\N~{~"
 static const UChar OPEN_DELIM  = 92;  // '\\' first char of OPEN
@@ -36,7 +36,7 @@
  * '}'.
  */
 NameUnicodeTransliterator::NameUnicodeTransliterator(UnicodeFilter* adoptedFilter) :
-    Transliterator(_ID, adoptedFilter) {
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter) {
 }
 
 /**

Index: name2uni.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/name2uni.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- name2uni.h	10 Sep 2003 02:42:23 -0000	1.3
+++ name2uni.h	6 Apr 2004 10:08:48 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -24,14 +24,7 @@
  * @author Alan Liu
  */
 class U_I18N_API NameUnicodeTransliterator : public Transliterator {
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
- public:
+public:
 
     /**
      * Constructs a transliterator.
@@ -65,14 +58,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -88,9 +81,6 @@
     virtual void handleTransliterate(Replaceable& text, UTransPosition& offset,
                                      UBool isIncremental) const;
 
- private:
-
-    static const char _ID[];
 };
 
 U_NAMESPACE_END

Index: nfrs.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nfrs.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- nfrs.cpp	10 Sep 2003 02:42:23 -0000	1.5
+++ nfrs.cpp	6 Apr 2004 10:08:48 -0000	1.6
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-*   Copyright (C) 1997-2001, International Business Machines
+*   Copyright (C) 1997-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ******************************************************************************
 *   file name:  nfrs.cpp
@@ -266,7 +266,7 @@
     delete fractionRules[2];
 }
 
-UBool
+static UBool
 util_equalRules(const NFRule* rule1, const NFRule* rule2)
 {
     if (rule1) {

Index: nfrule.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nfrule.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- nfrule.cpp	10 Sep 2003 02:42:23 -0000	1.5
+++ nfrule.cpp	6 Apr 2004 10:08:48 -0000	1.6
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-*   Copyright (C) 1997-2001, International Business Machines
+*   Copyright (C) 1997-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ******************************************************************************
 *   file name:  nfrule.cpp

Index: nfsubs.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nfsubs.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- nfsubs.cpp	10 Sep 2003 02:42:23 -0000	1.5
+++ nfsubs.cpp	6 Apr 2004 10:08:49 -0000	1.6
@@ -437,9 +437,8 @@
     // of its own).  Derive a parse result and return it as a Long,
     // if possible, or a Double
     if (parsePosition.getIndex() != 0) {
-        double tempResult = (result.getType() == Formattable::kLong) ?
-            (double)result.getLong() :
-        result.getDouble();
+        UErrorCode status = U_ZERO_ERROR;
+        double tempResult = result.getDouble(&status);
 
         // composeRuleValue() produces a full parse result from
         // the partial parse result passed to this function from
@@ -829,13 +828,15 @@
             workPos.setIndex(0);
             Formattable temp;
             getRuleSet()->parse(workText, workPos, 10, temp);
-            digit = temp.getType() == Formattable::kLong ?
-                temp.getLong() :
-            (int32_t)temp.getDouble();
+            UErrorCode status = U_ZERO_ERROR;
+            digit = temp.getLong(&status);
+//            digit = temp.getType() == Formattable::kLong ?
+//               temp.getLong() :
+//            (int32_t)temp.getDouble();
 
             if (lenientParse && workPos.getIndex() == 0) {
                 if (!fmt) {
-                    UErrorCode status = U_ZERO_ERROR;
+                    status = U_ZERO_ERROR;
                     fmt = NumberFormat::createInstance(status);
                     if (U_FAILURE(status)) {
                         delete fmt;

Index: nortrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nortrans.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- nortrans.cpp	10 Sep 2003 02:42:23 -0000	1.5
+++ nortrans.cpp	6 Apr 2004 10:08:49 -0000	1.6
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -21,7 +21,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char NormalizationTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NormalizationTransliterator)
 
 /**
  * System registration hook.

Index: nortrans.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nortrans.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- nortrans.h	10 Sep 2003 02:42:23 -0000	1.3
+++ nortrans.h	6 Apr 2004 10:08:49 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001-2002, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -35,12 +35,6 @@
      */
     int32_t options;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
  public:
 
     /**
@@ -69,14 +63,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 

Index: nultrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nultrans.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- nultrans.cpp	10 Sep 2003 02:42:23 -0000	1.3
+++ nultrans.cpp	6 Apr 2004 10:08:49 -0000	1.4
@@ -16,13 +16,17 @@
 
 U_NAMESPACE_BEGIN
 
-const char NullTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NullTransliterator)
 
 // "Any-Null"
 const UChar NullTransliterator::ID[] = {65,110,121,45,0x4E, 0x75, 0x6C, 0x6C, 0x00};
 
 // "Null"
 const UChar NullTransliterator::SHORT_ID[] = {0x4E, 0x75, 0x6C, 0x6C, 0x00};
+
+NullTransliterator::NullTransliterator() : Transliterator(ID, 0) {}
+
+NullTransliterator::~NullTransliterator() {}
 
 Transliterator* NullTransliterator::clone(void) const {
     return new NullTransliterator();

Index: nultrans.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/nultrans.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- nultrans.h	10 Sep 2003 02:42:23 -0000	1.1
+++ nultrans.h	6 Apr 2004 10:08:49 -0000	1.2
@@ -69,35 +69,16 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const;
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID();
-
-private:
+    static UClassID getStaticClassID();
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
-
-inline NullTransliterator::NullTransliterator() : Transliterator(ID, 0) {}
-
-inline NullTransliterator::~NullTransliterator() {}
-
-inline UClassID
-NullTransliterator::getStaticClassID()
-{ return (UClassID)&fgClassID; }
-
-inline UClassID
-NullTransliterator::getDynamicClassID() const
-{ return NullTransliterator::getStaticClassID(); }
 
 U_NAMESPACE_END
 

Index: numfmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/numfmt.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- numfmt.cpp	10 Sep 2003 02:42:23 -0000	1.3
+++ numfmt.cpp	6 Apr 2004 10:08:49 -0000	1.4
@@ -35,6 +35,7 @@
 #include "uhash.h"
 #include "iculserv.h"
 #include "ucln_in.h"
+#include "cstring.h"
 #include <float.h>
 
 // If no number pattern can be located for a locale, this is the last
@@ -57,8 +58,6 @@
 
 U_NAMESPACE_BEGIN
 
-const char NumberFormat::fgClassID = 0; // Value is irrelevant
-
 // If the maximum base 10 exponent were 4, then the largest number would
 // be 99,999 which has 5 digits.
 const int32_t NumberFormat::fgMaxIntegerDigits = DBL_MAX_10_EXP + 1; // Should be ~40 ? --srl
@@ -156,6 +155,9 @@
     else if (obj.getType() == Formattable::kLong) {
         return format(obj.getLong(), appendTo, pos);
     }
+    else if (obj.getType() == Formattable::kInt64) {
+       return format(obj.getInt64(), appendTo, pos);
+    }
     // can't try to format a non-numeric object
     else {
         status = U_INVALID_FORMAT_ERROR;
@@ -164,6 +166,17 @@
 }
 
 // -------------------------------------
+
+UnicodeString& 
+NumberFormat::format(int64_t number,
+                     UnicodeString& appendTo,
+                     FieldPosition& pos) const
+{
+	// default so we don't introduce a new abstract method
+	return format((int32_t)number, appendTo, pos);
+}
+
+// -------------------------------------
 // Parses the string and save the result object as well
 // as the final parsed position.
 
@@ -196,6 +209,16 @@
 }
 
 // -------------------------------------
+// Formats a long number and save the result in a string.
+
+UnicodeString&
+NumberFormat::format(int64_t number, UnicodeString& appendTo) const
+{
+    FieldPosition pos(0);
+    return format(number, appendTo, pos);
+}
+
+// -------------------------------------
 // Parses the text and save the result object.  If the returned
 // parse position is 0, that means the parsing failed, the status
 // code needs to be set to failure.  Ignores the returned parse
@@ -316,7 +339,7 @@
 
 class ICUNumberFormatFactory : public ICUResourceBundleFactory {
 protected:
-  virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* service, UErrorCode& status) const {
+  virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
 // !!! kind is not an EStyles, need to determine how to handle this
 	  return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
   }
@@ -398,7 +421,7 @@
 	  return ((NumberFormat*)instance)->clone();
   }
 
-  virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
+  virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
 	LocaleKey& lkey = (LocaleKey&)key;
 	int32_t kind = lkey.kind();
 	Locale loc;
@@ -711,7 +734,9 @@
     if (U_FAILURE(status)) {
         delete f;
         f = NULL;
+        return NULL;
     }
+    f->setLocales(numberPatterns);
     return f;
 }
 

Index: quant.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/quant.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- quant.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ quant.cpp	6 Apr 2004 10:08:49 -0000	1.6
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2001, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 2001-2003, International Business Machines Corporation and others. All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
 *   07/26/01    aliu        Creation.
@@ -16,7 +16,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char Quantifier::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Quantifier)
 
 Quantifier::Quantifier(UnicodeFunctor *adoptedMatcher,
                        uint32_t _minCount, uint32_t _maxCount) {
@@ -29,6 +29,7 @@
 
 Quantifier::Quantifier(const Quantifier& o) :
     UnicodeFunctor(o),
+    UnicodeMatcher(o),
     matcher(o.matcher->clone()),
     minCount(o.minCount),
     maxCount(o.maxCount)

Index: quant.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/quant.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- quant.h	10 Sep 2003 02:42:24 -0000	1.4
+++ quant.h	6 Apr 2004 10:08:49 -0000	1.5
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2001, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 2001-2003, International Business Machines Corporation and others. All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
 *   07/26/01    aliu        Creation.
@@ -101,14 +101,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  private:
 
@@ -119,12 +119,6 @@
     uint32_t minCount;
 
     uint32_t maxCount;
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: rbnf.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbnf.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- rbnf.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ rbnf.cpp	6 Apr 2004 10:08:49 -0000	1.6
@@ -45,7 +45,9 @@
 #define kHalfMaxDouble (double)(1 << kSomeNumberOfBitsDiv2)
 #define kMaxDouble (kHalfMaxDouble * kHalfMaxDouble)
 
-const char RuleBasedNumberFormat::fgClassID = 0;
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
 
 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, const Locale& alocale, UParseError& perror, UErrorCode& status)
   : ruleSets(NULL)
@@ -86,8 +88,10 @@
     UResourceBundle* nfrb = ures_open(NULL, locale.getName(), &status);
     //    UResourceBundle* yuck = ures_getByKey(nfrb, fmt_tag, NULL, &status);
     //    const UChar* description = ures_getString(yuck, &len, &status);
-    const UChar* description = ures_getStringByKey(nfrb, fmt_tag, &len, &status);
     if (U_SUCCESS(status)) {
+        setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status),
+                     ures_getLocaleByType(nfrb, ULOC_ACTUAL_LOCALE, &status));
+        const UChar* description = ures_getStringByKey(nfrb, fmt_tag, &len, &status);
         UnicodeString desc(description, len);
         UParseError perror;
         init (desc, perror, status);
@@ -241,7 +245,7 @@
 UnicodeString&
 RuleBasedNumberFormat::format(int32_t number,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos) const
+                              FieldPosition& /* pos */) const
 {
     if (defaultRuleSet) defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length());
     return toAppendTo;
@@ -251,7 +255,7 @@
 UnicodeString&
 RuleBasedNumberFormat::format(int64_t number,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos) const
+                              FieldPosition& /* pos */) const
 {
     if (defaultRuleSet) defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
     return toAppendTo;
@@ -261,7 +265,7 @@
 UnicodeString&
 RuleBasedNumberFormat::format(double number,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos) const
+                              FieldPosition& /* pos */) const
 {
     if (defaultRuleSet) defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
     return toAppendTo;
@@ -272,7 +276,7 @@
 RuleBasedNumberFormat::format(int32_t number,
                               const UnicodeString& ruleSetName,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos,
+                              FieldPosition& /* pos */,
                               UErrorCode& status) const
 {
     // return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
@@ -295,7 +299,7 @@
 RuleBasedNumberFormat::format(int64_t number,
                               const UnicodeString& ruleSetName,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos,
+                              FieldPosition& /* pos */,
                               UErrorCode& status) const
 {
     if (U_SUCCESS(status)) {
@@ -327,7 +331,7 @@
 RuleBasedNumberFormat::format(double number,
                               const UnicodeString& ruleSetName,
                               UnicodeString& toAppendTo,
-                              FieldPosition& pos,
+                              FieldPosition& /* pos */,
                               UErrorCode& status) const
 {
     if (U_SUCCESS(status)) {
@@ -442,7 +446,7 @@
 
 
 void
-RuleBasedNumberFormat::init(const UnicodeString& rules, UParseError& pErr, UErrorCode& status)
+RuleBasedNumberFormat::init(const UnicodeString& rules, UParseError& /* pErr */, UErrorCode& status)
 {
     // TODO: implement UParseError
     // Note: this can leave ruleSets == NULL, so remaining code should check
@@ -729,6 +733,8 @@
     }
     return decimalFormatSymbols;
 }
+
+U_NAMESPACE_END
 
 /* U_HAVE_RBNF */
 #endif

Index: rbt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbt.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- rbt.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ rbt.cpp	6 Apr 2004 10:08:49 -0000	1.5
@@ -21,13 +21,13 @@
 
 U_NAMESPACE_BEGIN
 
-const char RuleBasedTransliterator::fgClassID = 0; // Value is irrelevant
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTransliterator)
 
 void RuleBasedTransliterator::_construct(const UnicodeString& rules,
                                          UTransDirection direction,
                                          UParseError& parseError,
                                          UErrorCode& status) {
-    data = 0;
+    fData = 0;
     isDataOwned = TRUE;
     if (U_FAILURE(status)) {
         return;
@@ -45,17 +45,99 @@
         return;
     }
 
-    data = parser.orphanData();
-    setMaximumContextLength(data->ruleSet.getMaximumContextLength());
+    fData = parser.orphanData();
+    setMaximumContextLength(fData->ruleSet.getMaximumContextLength());
+}
+
+/**
+ * Constructs a new transliterator from the given rules.
+ * @param id            the id for the transliterator.
+ * @param rules         rules, separated by ';'
+ * @param direction     either FORWARD or REVERSE.
+ * @param adoptedFilter the filter for this transliterator.
+ * @param parseError    Struct to recieve information on position 
+ *                      of error if an error is encountered
+ * @param status        Output param set to success/failure code.
+ * @exception IllegalArgumentException if rules are malformed
+ * or direction is invalid.
+ */
+RuleBasedTransliterator::RuleBasedTransliterator(
+                            const UnicodeString& id,
+                            const UnicodeString& rules,
+                            UTransDirection direction,
+                            UnicodeFilter* adoptedFilter,
+                            UParseError& parseError,
+                            UErrorCode& status) :
+    Transliterator(id, adoptedFilter) {
+    _construct(rules, direction,parseError,status);
+}
+
+/**
+ * Constructs a new transliterator from the given rules.
+ * @param id            the id for the transliterator.
+ * @param rules         rules, separated by ';'
+ * @param direction     either FORWARD or REVERSE.
+ * @param adoptedFilter the filter for this transliterator.
+ * @param status        Output param set to success/failure code.
+ * @exception IllegalArgumentException if rules are malformed
+ * or direction is invalid.
+ */
+RuleBasedTransliterator::RuleBasedTransliterator(
+                            const UnicodeString& id,
+                            const UnicodeString& rules,
+                            UTransDirection direction,
+                            UnicodeFilter* adoptedFilter,
+                            UErrorCode& status) :
+    Transliterator(id, adoptedFilter) {
+    UParseError parseError;
+    _construct(rules, direction,parseError, status);
+}
+
+/**
+ * Covenience constructor with no filter.
+ */
+RuleBasedTransliterator::RuleBasedTransliterator(
+                            const UnicodeString& id,
+                            const UnicodeString& rules,
+                            UTransDirection direction,
+                            UErrorCode& status) :
+    Transliterator(id, 0) {
+    UParseError parseError;
+    _construct(rules, direction,parseError, status);
+}
+
+/**
+ * Covenience constructor with no filter and FORWARD direction.
+ */
+RuleBasedTransliterator::RuleBasedTransliterator(
+                            const UnicodeString& id,
+                            const UnicodeString& rules,
+                            UErrorCode& status) :
+    Transliterator(id, 0) {
+    UParseError parseError;
+    _construct(rules, UTRANS_FORWARD, parseError, status);
+}
+
+/**
+ * Covenience constructor with FORWARD direction.
+ */
+RuleBasedTransliterator::RuleBasedTransliterator(
+                            const UnicodeString& id,
+                            const UnicodeString& rules,
+                            UnicodeFilter* adoptedFilter,
+                            UErrorCode& status) :
+    Transliterator(id, adoptedFilter) {
+    UParseError parseError;
+    _construct(rules, UTRANS_FORWARD,parseError, status);
 }
 
 RuleBasedTransliterator::RuleBasedTransliterator(const UnicodeString& id,
                                  const TransliterationRuleData* theData,
                                  UnicodeFilter* adoptedFilter) :
     Transliterator(id, adoptedFilter),
-    data((TransliterationRuleData*)theData), // cast away const
+    fData((TransliterationRuleData*)theData), // cast away const
     isDataOwned(FALSE) {
-    setMaximumContextLength(data->ruleSet.getMaximumContextLength());
+    setMaximumContextLength(fData->ruleSet.getMaximumContextLength());
 }
 
 /**
@@ -65,9 +147,9 @@
                                                  TransliterationRuleData* theData,
                                                  UBool isDataAdopted) :
     Transliterator(id, 0),
-    data(theData),
+    fData(theData),
     isDataOwned(isDataAdopted) {
-    setMaximumContextLength(data->ruleSet.getMaximumContextLength());
+    setMaximumContextLength(fData->ruleSet.getMaximumContextLength());
 }
 
 /**
@@ -75,7 +157,7 @@
  */
 RuleBasedTransliterator::RuleBasedTransliterator(
         const RuleBasedTransliterator& other) :
-    Transliterator(other), data(other.data),
+    Transliterator(other), fData(other.fData),
     isDataOwned(other.isDataOwned) {
 
     // The data object may or may not be owned.  If it is not owned we
@@ -88,7 +170,7 @@
     // will be later deleted.  System transliterators contain
     // non-owned data.
     if (isDataOwned) {
-        data = new TransliterationRuleData(*other.data);
+        fData = new TransliterationRuleData(*other.fData);
     }
 }
 
@@ -98,7 +180,7 @@
 RuleBasedTransliterator::~RuleBasedTransliterator() {
     // Delete the data object only if we own it.
     if (isDataOwned) {
-        delete data;
+        delete fData;
     }
 }
 
@@ -145,30 +227,36 @@
         loopLimit <<= 4;
     }
 
+    if (isDataOwned==FALSE) {
+        fData->lock();
+    }
     while (index.start < index.limit &&
            loopCount <= loopLimit &&
-           data->ruleSet.transliterate(text, index, isIncremental)) {
+           fData->ruleSet.transliterate(text, index, isIncremental)) {
         ++loopCount;
     }
+    if (isDataOwned==FALSE) {
+        fData->unlock();
+    }
 }
 
 UnicodeString& RuleBasedTransliterator::toRules(UnicodeString& rulesSource,
                                                 UBool escapeUnprintable) const {
-    return data->ruleSet.toRules(rulesSource, escapeUnprintable);
+    return fData->ruleSet.toRules(rulesSource, escapeUnprintable);
 }
 
 /**
  * Implement Transliterator framework
  */
 void RuleBasedTransliterator::handleGetSourceSet(UnicodeSet& result) const {
-    data->ruleSet.getSourceTargetSet(result, FALSE);
+    fData->ruleSet.getSourceTargetSet(result, FALSE);
 }
 
 /**
  * Override Transliterator framework
  */
 UnicodeSet& RuleBasedTransliterator::getTargetSet(UnicodeSet& result) const {
-    return data->ruleSet.getSourceTargetSet(result, TRUE);
+    return fData->ruleSet.getSourceTargetSet(result, TRUE);
 }
 
 U_NAMESPACE_END

Index: rbt.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbt.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rbt.h	10 Sep 2003 02:42:24 -0000	1.1
+++ rbt.h	6 Apr 2004 10:08:49 -0000	1.2
@@ -284,12 +284,13 @@
  * @internal Use transliterator factory methods instead since this class will be removed in that release.
  */
 class U_I18N_API RuleBasedTransliterator : public Transliterator {
-
+private:
     /**
      * The data object is immutable, so we can freely share it with
      * other instances of RBT, as long as we do NOT own this object.
+     *  TODO:  data is no longer immutable.  See bugs #1866, 2155
      */
-    TransliterationRuleData* data;
+    TransliterationRuleData* fData;
 
     /**
      * If true, we own the data object and must delete it.
@@ -350,7 +351,7 @@
                             const UnicodeString& rules,
                             UnicodeFilter* adoptedFilter,
                             UErrorCode& status);
- private:
+private:
 
      friend class TransliteratorRegistry; // to access TransliterationRuleData convenience ctor
     /**
@@ -376,7 +377,7 @@
                             TransliterationRuleData* data,
                             UBool isDataAdopted);
 
- public:
+public:
 
     /**
      * Copy constructor.
@@ -392,7 +393,7 @@
      */
     Transliterator* clone(void) const;
 
- protected:
+protected:
     /**
      * Implements {@link Transliterator#handleTransliterate}.
      * @internal Use transliterator factory methods instead since this class will be removed in that release.
@@ -400,7 +401,7 @@
     virtual void handleTransliterate(Replaceable& text, UTransPosition& offsets,
                                      UBool isIncremental) const;
 
- public:
+public:
     /**
      * Return a representation of this transliterator as source rules.
      * These rules will produce an equivalent transliterator if used
@@ -416,13 +417,13 @@
     virtual UnicodeString& toRules(UnicodeString& result,
                                    UBool escapeUnprintable) const;
 
- protected:
+protected:
     /**
      * Implement Transliterator framework
      */
     virtual void handleGetSourceSet(UnicodeSet& result) const;
 
- public:
+public:
     /**
      * Override Transliterator framework
      */
@@ -439,7 +440,7 @@
      * @return          The class ID for all objects of this class.
      * @internal Use transliterator factory methods instead since this class will be removed in that release.
      */
-    static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID(void);
 
     /**
      * Returns a unique class ID <b>polymorphically</b>.  This method
@@ -463,102 +464,16 @@
      * class have the same class ID.  Objects of other classes have
      * different class IDs.
      */
-    virtual UClassID getDynamicClassID(void) const { return getStaticClassID(); };
+    virtual UClassID getDynamicClassID(void) const;
 
 private:
 
-    /**
-     * Class identifier for RuleBasedTransliterator.
-     */
-    static const char fgClassID;
-
     void _construct(const UnicodeString& rules,
                     UTransDirection direction,
                     UParseError& parseError,
                     UErrorCode& status);
 };
 
-/**
- * Constructs a new transliterator from the given rules.
- * @param id            the id for the transliterator.
- * @param rules         rules, separated by ';'
- * @param direction     either FORWARD or REVERSE.
- * @param adoptedFilter the filter for this transliterator.
- * @param parseError    Struct to recieve information on position 
- *                      of error if an error is encountered
- * @param status        Output param set to success/failure code.
- * @exception IllegalArgumentException if rules are malformed
- * or direction is invalid.
- */
-inline RuleBasedTransliterator::RuleBasedTransliterator(
-                            const UnicodeString& id,
-                            const UnicodeString& rules,
-                            UTransDirection direction,
-                            UnicodeFilter* adoptedFilter,
-                            UParseError& parseError,
-                            UErrorCode& status) :
-    Transliterator(id, adoptedFilter) {
-    _construct(rules, direction,parseError,status);
-}
-
-/**
- * Constructs a new transliterator from the given rules.
- * @param id            the id for the transliterator.
- * @param rules         rules, separated by ';'
- * @param direction     either FORWARD or REVERSE.
- * @param adoptedFilter the filter for this transliterator.
- * @param status        Output param set to success/failure code.
- * @exception IllegalArgumentException if rules are malformed
- * or direction is invalid.
- */
-inline RuleBasedTransliterator::RuleBasedTransliterator(
-                            const UnicodeString& id,
-                            const UnicodeString& rules,
-                            UTransDirection direction,
-                            UnicodeFilter* adoptedFilter,
-                            UErrorCode& status) :
-    Transliterator(id, adoptedFilter) {
-    UParseError parseError;
-    _construct(rules, direction,parseError, status);
-}
-
-/**
- * Covenience constructor with no filter.
- */
-inline RuleBasedTransliterator::RuleBasedTransliterator(
-                            const UnicodeString& id,
-                            const UnicodeString& rules,
-                            UTransDirection direction,
-                            UErrorCode& status) :
-    Transliterator(id, 0) {
-    UParseError parseError;
-    _construct(rules, direction,parseError, status);
-}
-
-/**
- * Covenience constructor with no filter and FORWARD direction.
- */
-inline RuleBasedTransliterator::RuleBasedTransliterator(
-                            const UnicodeString& id,
-                            const UnicodeString& rules,
-                            UErrorCode& status) :
-    Transliterator(id, 0) {
-    UParseError parseError;
-    _construct(rules, UTRANS_FORWARD, parseError, status);
-}
-
-/**
- * Covenience constructor with FORWARD direction.
- */
-inline RuleBasedTransliterator::RuleBasedTransliterator(
-                            const UnicodeString& id,
-                            const UnicodeString& rules,
-                            UnicodeFilter* adoptedFilter,
-                            UErrorCode& status) :
-    Transliterator(id, adoptedFilter) {
-    UParseError parseError;
-    _construct(rules, UTRANS_FORWARD,parseError, status);
-}
 
 U_NAMESPACE_END
 

Index: rbt_data.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbt_data.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- rbt_data.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ rbt_data.cpp	6 Apr 2004 10:08:49 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1999, International Business Machines
+*   Copyright (C) 1999-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -9,6 +9,7 @@
 */
 
 #include "unicode/utypes.h"
+#include "umutex.h"
 
 #if !UCONFIG_NO_TRANSLITERATION
 
@@ -22,7 +23,7 @@
 
 TransliterationRuleData::TransliterationRuleData(UErrorCode& status)
  : UMemory(), ruleSet(status),
-    variableNames(0), variables(0)
+    variableNames(0), variables(0), fLock(NULL)
 {
     if (U_FAILURE(status)) {
         return;
@@ -43,7 +44,8 @@
 TransliterationRuleData::TransliterationRuleData(const TransliterationRuleData& other) :
     UMemory(other), ruleSet(other.ruleSet),
     variablesBase(other.variablesBase),
-    variablesLength(other.variablesLength)
+    variablesLength(other.variablesLength),
+    fLock(NULL)     /* The mutex must NOT be copied from the source data */
 {
     UErrorCode status = U_ZERO_ERROR;
     variableNames = new Hashtable(status);
@@ -83,6 +85,7 @@
         }
         uprv_free(variables);
     }
+    umtx_destroy(&fLock);
 }
 
 UnicodeFunctor*
@@ -102,6 +105,18 @@
     UnicodeFunctor *f = lookup(standIn);
     return (f != 0) ? f->toReplacer() : 0;
 }
+
+void
+TransliterationRuleData::lock() {
+    umtx_lock(&fLock);
+}
+
+void
+TransliterationRuleData::unlock() {
+    umtx_unlock(&fLock);
+}
+
+
 
 U_NAMESPACE_END
 

Index: rbt_data.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbt_data.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- rbt_data.h	10 Sep 2003 02:42:24 -0000	1.4
+++ rbt_data.h	6 Apr 2004 10:08:49 -0000	1.5
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) {1999}, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 1999-2003, International Business Machines Corporation and others. All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
 *   11/17/99    aliu        Creation.
@@ -9,6 +9,7 @@
 #define RBT_DATA_H
 
 #include "unicode/utypes.h"
+#include "unicode/uclean.h"
 
 #if !UCONFIG_NO_TRANSLITERATION
 
@@ -129,8 +130,19 @@
      */
     UnicodeReplacer* lookupReplacer(UChar32 standIn) const;
 
+    /**
+     *  Acquire the mutex lock for this data.
+     */
+    void lock();
+
+    /**
+     *  Release the mutex lock for this data
+     */
+    void unlock();
+
 private:
     TransliterationRuleData &operator=(const TransliterationRuleData &other); // forbid copying of this class
+    UMTX    fLock;
 };
 
 U_NAMESPACE_END

Index: rbt_pars.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rbt_pars.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- rbt_pars.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ rbt_pars.cpp	6 Apr 2004 10:08:49 -0000	1.6
@@ -29,7 +29,7 @@
 #include "rbt_rule.h"
 #include "strmatch.h"
 #include "strrepl.h"
-#include "symtable.h"
+#include "unicode/symtable.h"
 #include "tridpars.h"
 #include "uvector.h"
 #include "util.h"
@@ -1093,7 +1093,7 @@
  * Set the maximum backup to 'backup', in response to a pragma
  * statement.
  */
-void TransliteratorParser::pragmaMaximumBackup(int32_t backup) {
+void TransliteratorParser::pragmaMaximumBackup(int32_t /*backup*/) {
     //TODO Finish
 }
 
@@ -1101,7 +1101,7 @@
  * Begin normalizing all rules using the given mode, in response
  * to a pragma statement.
  */
-void TransliteratorParser::pragmaNormalizeRules(UNormalizationMode mode) {
+void TransliteratorParser::pragmaNormalizeRules(UNormalizationMode /*mode*/) {
     //TODO Finish
 }
 
@@ -1417,7 +1417,7 @@
  */
 UChar TransliteratorParser::parseSet(const UnicodeString& rule,
                                           ParsePosition& pos) {
-    UnicodeSet* set = new UnicodeSet(rule, pos, *parseData, status);
+    UnicodeSet* set = new UnicodeSet(rule, pos, USET_IGNORE_SPACE, parseData, status);
     set->compact();
     return generateStandInFor(set);
 }

Index: regexcmp.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/regexcmp.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- regexcmp.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ regexcmp.cpp	6 Apr 2004 10:08:49 -0000	1.2
@@ -159,12 +159,12 @@
         //    the search will stop there, if not before.
         //
         tableEl = &gRuleParseStateTable[state];
-        REGEX_SCAN_DEBUG_PRINTF( "char, line, col = (\'%c\', %d, %d)    state=%s ",
-            fC.fChar, fLineNum, fCharNum, RegexStateNames[state]);
+        REGEX_SCAN_DEBUG_PRINTF(("char, line, col = (\'%c\', %d, %d)    state=%s ", 
+            fC.fChar, fLineNum, fCharNum, RegexStateNames[state]));
 
         for (;;) {    // loop through table rows belonging to this state, looking for one
                       //   that matches the current input char.
-            REGEX_SCAN_DEBUG_PRINTF( ".");
+            REGEX_SCAN_DEBUG_PRINTF(("."));
             if (tableEl->fCharClass < 127 && fC.fQuoted == FALSE &&   tableEl->fCharClass == fC.fChar) {
                 // Table row specified an individual character, not a set, and
                 //   the input character is not quoted, and
@@ -198,7 +198,7 @@
             // No match on this row, advance to the next  row for this state,
             tableEl++;
         }
-        REGEX_SCAN_DEBUG_PRINTF("\n");
+        REGEX_SCAN_DEBUG_PRINTF(("\n"));
 
         //
         // We've found the row of the state table that matches the current input
@@ -215,7 +215,7 @@
             fStackPtr++;
             if (fStackPtr >= kStackSize) {
                 error(U_REGEX_INTERNAL_ERROR);
-                REGEX_SCAN_DEBUG_PRINTF( "RegexCompile::parse() - state stack overflow.\n");
+                REGEX_SCAN_DEBUG_PRINTF(("RegexCompile::parse() - state stack overflow.\n"));
                 fStackPtr--;
             }
             fStack[fStackPtr] = tableEl->fPushState;
@@ -318,19 +318,6 @@
         fRXPat->fSets8[i].init(s);
     }
 
-    //
-    // A stupid bit of non-sense to prevent code coverage testing from complaining
-    //   about the pattern.dump() debug function.  Go through the motions of dumping,
-    //   even though, without the #define set, it will do nothing.
-    //
-#ifndef REGEX_DUMP_DEBUG
-    static UBool phonyDumpDone = FALSE;
-    if (phonyDumpDone==FALSE) {
-        fRXPat->dump();
-        phonyDumpDone = TRUE;
-    }
-#endif
-
 }
 
 
@@ -1089,11 +1076,27 @@
         break;
 
     case doBackslashB:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_B, 1), *fStatus);
+        {
+            #if  UCONFIG_NO_BREAK_ITERATION==1
+            if (fModeFlags & UREGEX_UWORD) {
+                error(U_UNSUPPORTED_ERROR);
+            }
+            #endif
+            int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
+            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 1), *fStatus);
+        }
         break;
 
     case doBackslashb:
-        fRXPat->fCompiledPat->addElement(URX_BUILD(URX_BACKSLASH_B, 0), *fStatus);
+        {
+            #if  UCONFIG_NO_BREAK_ITERATION==1
+            if (fModeFlags & UREGEX_UWORD) {
+                error(U_UNSUPPORTED_ERROR);
+            }
+            #endif
+            int32_t op = (fModeFlags & UREGEX_UWORD)? URX_BACKSLASH_BU : URX_BACKSLASH_B;
+            fRXPat->fCompiledPat->addElement(URX_BUILD(op, 0), *fStatus);
+        }
         break;
 
     case doBackslashD:
@@ -1197,7 +1200,7 @@
             //  the compiled code for it. 
             // Because capture groups can be forward-referenced by back-references,
             //  we fill the operand with the capture group number.  At the end
-            //  of compilation, it will be changed to the variables location.
+            //  of compilation, it will be changed to the variable's location.
             U_ASSERT(groupNum > 0);
             int32_t  op;
             if (fModeFlags & UREGEX_CASE_INSENSITIVE) {
@@ -1210,12 +1213,6 @@
         break;
 
 
-    case doOctal:
-        error(U_REGEX_UNIMPLEMENTED);
-        break;
-
-
-
     case doPossessivePlus:
         // Possessive ++ quantifier.
         // Compiles to
@@ -1331,6 +1328,7 @@
             case 0x69: /* 'i' */   bit = UREGEX_CASE_INSENSITIVE; break;
             case 0x6d: /* 'm' */   bit = UREGEX_MULTILINE;        break;
             case 0x73: /* 's' */   bit = UREGEX_DOTALL;           break;
+            case 0x77: /* 'w' */   bit = UREGEX_UWORD;            break;
             case 0x78: /* 'x' */   bit = UREGEX_COMMENTS;         break;
             case 0x2d: /* '-' */   fSetModeFlag = FALSE;          break;
             default:
@@ -1382,6 +1380,10 @@
         }
         break;
 
+    case doBadModeFlag:
+        error(U_REGEX_INVALID_FLAG);
+        break;
+
     case doSuppressComments:
         // We have just scanned a '(?'.  We now need to prevent the character scanner from
         // treating a '#' as a to-the-end-of-line comment.
@@ -1672,8 +1674,7 @@
         // The item just processed is a parenthesized block.
         theLoc = fMatchOpenParen;   // A slot is already reserved for us.
         U_ASSERT(theLoc > 0);
-        uint32_t  opAtTheLoc = fRXPat->fCompiledPat->elementAti(theLoc);
-        U_ASSERT(URX_TYPE(opAtTheLoc) == URX_NOP);
+        U_ASSERT(URX_TYPE(((uint32_t)fRXPat->fCompiledPat->elementAti(theLoc))) == URX_NOP);
     }
     else {
         // Item just compiled is a single thing, a ".", or a single char, or a set reference.
@@ -1682,7 +1683,7 @@
         fixLiterals(TRUE);  // If last item was a string, separate the last char.
         theLoc = fRXPat->fCompiledPat->size()-1;
         if (reserveLoc) {
-            int32_t opAtTheLoc = fRXPat->fCompiledPat->elementAti(theLoc);
+            /*int32_t opAtTheLoc = fRXPat->fCompiledPat->elementAti(theLoc);*/
             int32_t  nop = URX_BUILD(URX_NOP, 0);
             fRXPat->fCompiledPat->insertElementAt(nop, theLoc, *fStatus);
         }
@@ -2121,6 +2122,7 @@
         case URX_START_CAPTURE:
         case URX_END_CAPTURE:
         case URX_BACKSLASH_B:
+        case URX_BACKSLASH_BU:
         case URX_BACKSLASH_G:
         case URX_BACKSLASH_Z:
         case URX_DOLLAR:
@@ -2398,10 +2400,15 @@
                         loopEndLoc   = URX_VAL(loopEndLoc);
                 int32_t minLoopCount = fRXPat->fCompiledPat->elementAti(loc+2);
                 if (minLoopCount == 0) {
-                    loc = loopEndLoc;
-                } else {
-                    loc+=3;  // Skips over operands of CTR_INIT
-                }
+                    // Min Loop Count of 0, treat like a forward branch and
+                    //   move the current minimum length up to the target
+                    //   (end of loop) location.
+                    U_ASSERT(loopEndLoc <= end+1);
+                    if (forwardedLength.elementAti(loopEndLoc) > currentLen) {
+                        forwardedLength.setElementAt(currentLen, loopEndLoc);
+                    }
+                } 
+                loc+=3;  // Skips over operands of CTR_INIT
             }
             atStart = FALSE;
             break;
@@ -2499,7 +2506,7 @@
         fRXPat->fStartType   = START_STRING;
         fRXPat->fInitialChar = c;
     } else if (fRXPat->fStartType == START_LINE) {
-        // Match at start of line in Mulit-Line mode.
+        // Match at start of line in Multi-Line mode.
         // Nothing to do here; everything is already set.
     } else if (fRXPat->fMinMatchLen == 0) {
         // Zero length match possible.  We could start anywhere.
@@ -2586,6 +2593,7 @@
         case URX_START_CAPTURE:
         case URX_END_CAPTURE:
         case URX_BACKSLASH_B:
+        case URX_BACKSLASH_BU:
         case URX_BACKSLASH_G:
         case URX_BACKSLASH_Z:
         case URX_CARET:
@@ -2825,6 +2833,7 @@
         case URX_START_CAPTURE:
         case URX_END_CAPTURE:
         case URX_BACKSLASH_B:
+        case URX_BACKSLASH_BU:
         case URX_BACKSLASH_G:
         case URX_BACKSLASH_Z:
         case URX_CARET:
@@ -3078,6 +3087,7 @@
         case URX_DOTANY:
         case URX_FAIL:
         case URX_BACKSLASH_B:
+        case URX_BACKSLASH_BU:
         case URX_BACKSLASH_G:
         case URX_BACKSLASH_X:
         case URX_BACKSLASH_Z:
@@ -3445,11 +3455,11 @@
     }
 
     uset = new UnicodeSet(fRXPat->fPattern, pos,
-                         usetFlags, localStatus);
+                         usetFlags, NULL, localStatus);
     if (U_FAILURE(localStatus)) {
         //  TODO:  Get more accurate position of the error from UnicodeSet's return info.
         //         UnicodeSet appears to not be reporting correctly at this time.
-        REGEX_SCAN_DEBUG_PRINTF( "UnicodeSet parse postion.ErrorIndex = %d\n", pos.getIndex());
+        REGEX_SCAN_DEBUG_PRINTF(("UnicodeSet parse postion.ErrorIndex = %d\n", pos.getIndex()));
         error(localStatus);
         delete uset;
         return NULL;
@@ -3518,7 +3528,7 @@
     }
 
     // Build the UnicodeSet from the set pattern we just built up in a string.
-    uset = new UnicodeSet(setPattern,  usetFlags, *fStatus);
+    uset = new UnicodeSet(setPattern, usetFlags, NULL, *fStatus);
     if (U_FAILURE(*fStatus)) {
         delete uset;
         uset =  NULL;

Index: regexcst.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/regexcst.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- regexcst.h	10 Sep 2003 02:42:24 -0000	1.1
+++ regexcst.h	6 Apr 2004 10:08:49 -0000	1.2
@@ -32,7 +32,6 @@
     doRuleError,
     doIntevalLowerDigit,
     doBackslashs,
-    doOctal,
     doNGOpt,
     doBackslashw,
     doMismatchedParenErr,
@@ -80,6 +79,7 @@
     doExit,
     doNGInterval,
     doPatStart,
+    doBadModeFlag,
     doBackslashb,
     doPossessiveStar,
     doBackslashd,
@@ -112,15 +112,15 @@
     , {doDotAny, 46 /* . */, 14,0,  TRUE}     //  6 
     , {doCaret, 94 /* ^ */, 2,0,  TRUE}     //  7 
     , {doDollar, 36 /* $ */, 2,0,  TRUE}     //  8 
-    , {doNOP, 92 /* \ */, 79,0,  TRUE}     //  9 
+    , {doNOP, 92 /* \ */, 81,0,  TRUE}     //  9 
     , {doOrOperator, 124 /* | */, 2,0,  TRUE}     //  10 
     , {doCloseParen, 41 /* ) */, 255,0,  TRUE}     //  11 
     , {doPatFinish, 253, 2,0,  FALSE}     //  12 
-    , {doRuleError, 255, 100,0,  FALSE}     //  13 
-    , {doNOP, 42 /* * */, 57,0,  TRUE}     //  14      expr-quant
-    , {doNOP, 43 /* + */, 60,0,  TRUE}     //  15 
-    , {doNOP, 63 /* ? */, 63,0,  TRUE}     //  16 
-    , {doIntervalInit, 123 /* { */, 66,0,  TRUE}     //  17 
+    , {doRuleError, 255, 101,0,  FALSE}     //  13 
+    , {doNOP, 42 /* * */, 59,0,  TRUE}     //  14      expr-quant
+    , {doNOP, 43 /* + */, 62,0,  TRUE}     //  15 
+    , {doNOP, 63 /* ? */, 65,0,  TRUE}     //  16 
+    , {doIntervalInit, 123 /* { */, 68,0,  TRUE}     //  17 
     , {doNOP, 40 /* ( */, 23,0,  TRUE}     //  18 
     , {doNOP, 255, 20,0,  FALSE}     //  19 
     , {doOrOperator, 124 /* | */, 2,0,  TRUE}     //  20      expr-cont
@@ -128,7 +128,7 @@
     , {doNOP, 255, 2,0,  FALSE}     //  22 
     , {doSuppressComments, 63 /* ? */, 25,0,  TRUE}     //  23      open-paren-quant
     , {doNOP, 255, 27,0,  FALSE}     //  24 
-    , {doNOP, 35 /* # */, 46, 14, TRUE}     //  25      open-paren-quant2
+    , {doNOP, 35 /* # */, 47, 14, TRUE}     //  25      open-paren-quant2
     , {doNOP, 255, 29,0,  FALSE}     //  26 
     , {doSuppressComments, 63 /* ? */, 29,0,  TRUE}     //  27      open-paren
     , {doOpenCaptureParen, 255, 2, 14, FALSE}     //  28 
@@ -136,74 +136,75 @@
     , {doOpenAtomicParen, 62 /* > */, 2, 14, TRUE}     //  30 
     , {doOpenLookAhead, 61 /* = */, 2, 20, TRUE}     //  31 
     , {doOpenLookAheadNeg, 33 /* ! */, 2, 20, TRUE}     //  32 
-    , {doNOP, 60 /* < */, 43,0,  TRUE}     //  33 
-    , {doNOP, 35 /* # */, 46, 2, TRUE}     //  34 
-    , {doBeginMatchMode, 105 /* i */, 49,0,  FALSE}     //  35 
-    , {doBeginMatchMode, 109 /* m */, 49,0,  FALSE}     //  36 
-    , {doBeginMatchMode, 115 /* s */, 49,0,  FALSE}     //  37 
-    , {doBeginMatchMode, 120 /* x */, 49,0,  FALSE}     //  38 
-    , {doBeginMatchMode, 45 /* - */, 49,0,  FALSE}     //  39 
-    , {doConditionalExpr, 40 /* ( */, 100,0,  TRUE}     //  40 
-    , {doPerlInline, 123 /* { */, 100,0,  TRUE}     //  41 
-    , {doBadOpenParenType, 255, 100,0,  FALSE}     //  42 
-    , {doOpenLookBehind, 61 /* = */, 2, 20, TRUE}     //  43      open-paren-lookbehind
-    , {doOpenLookBehindNeg, 33 /* ! */, 2, 20, TRUE}     //  44 
-    , {doBadOpenParenType, 255, 100,0,  FALSE}     //  45 
-    , {doNOP, 41 /* ) */, 255,0,  TRUE}     //  46      paren-comment
-    , {doMismatchedParenErr, 253, 100,0,  FALSE}     //  47 
-    , {doNOP, 255, 46,0,  TRUE}     //  48 
-    , {doMatchMode, 105 /* i */, 49,0,  TRUE}     //  49      paren-flag
-    , {doMatchMode, 109 /* m */, 49,0,  TRUE}     //  50 
-    , {doMatchMode, 115 /* s */, 49,0,  TRUE}     //  51 
-    , {doMatchMode, 120 /* x */, 49,0,  TRUE}     //  52 
-    , {doMatchMode, 45 /* - */, 49,0,  TRUE}     //  53 
-    , {doSetMatchMode, 41 /* ) */, 2,0,  TRUE}     //  54 
-    , {doMatchModeParen, 58 /* : */, 2, 14, TRUE}     //  55 
-    , {doNOP, 255, 100,0,  FALSE}     //  56 
-    , {doNGStar, 63 /* ? */, 20,0,  TRUE}     //  57      quant-star
-    , {doPossessiveStar, 43 /* + */, 20,0,  TRUE}     //  58 
-    , {doStar, 255, 20,0,  FALSE}     //  59 
-    , {doNGPlus, 63 /* ? */, 20,0,  TRUE}     //  60      quant-plus
-    , {doPossessivePlus, 43 /* + */, 20,0,  TRUE}     //  61 
-    , {doPlus, 255, 20,0,  FALSE}     //  62 
-    , {doNGOpt, 63 /* ? */, 20,0,  TRUE}     //  63      quant-opt
-    , {doPossessiveOpt, 43 /* + */, 20,0,  TRUE}     //  64 
-    , {doOpt, 255, 20,0,  FALSE}     //  65 
-    , {doNOP, 129, 66,0,  TRUE}     //  66      interval-open
-    , {doNOP, 128, 69,0,  FALSE}     //  67 
-    , {doIntervalError, 255, 100,0,  FALSE}     //  68 
-    , {doIntevalLowerDigit, 128, 69,0,  TRUE}     //  69      interval-lower
-    , {doNOP, 44 /* , */, 73,0,  TRUE}     //  70 
-    , {doIntervalSame, 125 /* } */, 76,0,  TRUE}     //  71 
-    , {doIntervalError, 255, 100,0,  FALSE}     //  72 
-    , {doIntervalUpperDigit, 128, 73,0,  TRUE}     //  73      interval-upper
-    , {doNOP, 125 /* } */, 76,0,  TRUE}     //  74 
-    , {doIntervalError, 255, 100,0,  FALSE}     //  75 
-    , {doNGInterval, 63 /* ? */, 20,0,  TRUE}     //  76      interval-type
-    , {doPossessiveInterval, 43 /* + */, 20,0,  TRUE}     //  77 
-    , {doInterval, 255, 20,0,  FALSE}     //  78 
-    , {doBackslashA, 65 /* A */, 2,0,  TRUE}     //  79      backslash
-    , {doBackslashB, 66 /* B */, 2,0,  TRUE}     //  80 
-    , {doBackslashb, 98 /* b */, 2,0,  TRUE}     //  81 
-    , {doBackslashd, 100 /* d */, 14,0,  TRUE}     //  82 
-    , {doBackslashD, 68 /* D */, 14,0,  TRUE}     //  83 
-    , {doBackslashG, 71 /* G */, 2,0,  TRUE}     //  84 
-    , {doProperty, 78 /* N */, 14,0,  FALSE}     //  85 
-    , {doProperty, 112 /* p */, 14,0,  FALSE}     //  86 
-    , {doProperty, 80 /* P */, 14,0,  FALSE}     //  87 
-    , {doEnterQuoteMode, 81 /* Q */, 2,0,  TRUE}     //  88 
-    , {doBackslashS, 83 /* S */, 14,0,  TRUE}     //  89 
-    , {doBackslashs, 115 /* s */, 14,0,  TRUE}     //  90 
-    , {doBackslashW, 87 /* W */, 14,0,  TRUE}     //  91 
-    , {doBackslashw, 119 /* w */, 14,0,  TRUE}     //  92 
-    , {doBackslashX, 88 /* X */, 14,0,  TRUE}     //  93 
-    , {doBackslashZ, 90 /* Z */, 2,0,  TRUE}     //  94 
-    , {doBackslashz, 122 /* z */, 2,0,  TRUE}     //  95 
-    , {doOctal, 48 /* 0 */, 14,0,  TRUE}     //  96 
-    , {doBackRef, 128, 14,0,  TRUE}     //  97 
-    , {doEscapeError, 253, 100,0,  FALSE}     //  98 
-    , {doLiteralChar, 255, 14,0,  TRUE}     //  99 
-    , {doExit, 255, 100,0,  TRUE}     //  100      errorDeath
+    , {doNOP, 60 /* < */, 44,0,  TRUE}     //  33 
+    , {doNOP, 35 /* # */, 47, 2, TRUE}     //  34 
+    , {doBeginMatchMode, 105 /* i */, 50,0,  FALSE}     //  35 
+    , {doBeginMatchMode, 109 /* m */, 50,0,  FALSE}     //  36 
+    , {doBeginMatchMode, 115 /* s */, 50,0,  FALSE}     //  37 
+    , {doBeginMatchMode, 119 /* w */, 50,0,  FALSE}     //  38 
+    , {doBeginMatchMode, 120 /* x */, 50,0,  FALSE}     //  39 
+    , {doBeginMatchMode, 45 /* - */, 50,0,  FALSE}     //  40 
+    , {doConditionalExpr, 40 /* ( */, 101,0,  TRUE}     //  41 
+    , {doPerlInline, 123 /* { */, 101,0,  TRUE}     //  42 
+    , {doBadOpenParenType, 255, 101,0,  FALSE}     //  43 
+    , {doOpenLookBehind, 61 /* = */, 2, 20, TRUE}     //  44      open-paren-lookbehind
+    , {doOpenLookBehindNeg, 33 /* ! */, 2, 20, TRUE}     //  45 
+    , {doBadOpenParenType, 255, 101,0,  FALSE}     //  46 
+    , {doNOP, 41 /* ) */, 255,0,  TRUE}     //  47      paren-comment
+    , {doMismatchedParenErr, 253, 101,0,  FALSE}     //  48 
+    , {doNOP, 255, 47,0,  TRUE}     //  49 
+    , {doMatchMode, 105 /* i */, 50,0,  TRUE}     //  50      paren-flag
+    , {doMatchMode, 109 /* m */, 50,0,  TRUE}     //  51 
+    , {doMatchMode, 115 /* s */, 50,0,  TRUE}     //  52 
+    , {doMatchMode, 119 /* w */, 50,0,  TRUE}     //  53 
+    , {doMatchMode, 120 /* x */, 50,0,  TRUE}     //  54 
+    , {doMatchMode, 45 /* - */, 50,0,  TRUE}     //  55 
+    , {doSetMatchMode, 41 /* ) */, 2,0,  TRUE}     //  56 
+    , {doMatchModeParen, 58 /* : */, 2, 14, TRUE}     //  57 
+    , {doBadModeFlag, 255, 101,0,  FALSE}     //  58 
+    , {doNGStar, 63 /* ? */, 20,0,  TRUE}     //  59      quant-star
+    , {doPossessiveStar, 43 /* + */, 20,0,  TRUE}     //  60 
+    , {doStar, 255, 20,0,  FALSE}     //  61 
+    , {doNGPlus, 63 /* ? */, 20,0,  TRUE}     //  62      quant-plus
+    , {doPossessivePlus, 43 /* + */, 20,0,  TRUE}     //  63 
+    , {doPlus, 255, 20,0,  FALSE}     //  64 
+    , {doNGOpt, 63 /* ? */, 20,0,  TRUE}     //  65      quant-opt
+    , {doPossessiveOpt, 43 /* + */, 20,0,  TRUE}     //  66 
+    , {doOpt, 255, 20,0,  FALSE}     //  67 
+    , {doNOP, 129, 68,0,  TRUE}     //  68      interval-open
+    , {doNOP, 128, 71,0,  FALSE}     //  69 
+    , {doIntervalError, 255, 101,0,  FALSE}     //  70 
+    , {doIntevalLowerDigit, 128, 71,0,  TRUE}     //  71      interval-lower
+    , {doNOP, 44 /* , */, 75,0,  TRUE}     //  72 
+    , {doIntervalSame, 125 /* } */, 78,0,  TRUE}     //  73 
+    , {doIntervalError, 255, 101,0,  FALSE}     //  74 
+    , {doIntervalUpperDigit, 128, 75,0,  TRUE}     //  75      interval-upper
+    , {doNOP, 125 /* } */, 78,0,  TRUE}     //  76 
+    , {doIntervalError, 255, 101,0,  FALSE}     //  77 
+    , {doNGInterval, 63 /* ? */, 20,0,  TRUE}     //  78      interval-type
+    , {doPossessiveInterval, 43 /* + */, 20,0,  TRUE}     //  79 
+    , {doInterval, 255, 20,0,  FALSE}     //  80 
+    , {doBackslashA, 65 /* A */, 2,0,  TRUE}     //  81      backslash
+    , {doBackslashB, 66 /* B */, 2,0,  TRUE}     //  82 
+    , {doBackslashb, 98 /* b */, 2,0,  TRUE}     //  83 
+    , {doBackslashd, 100 /* d */, 14,0,  TRUE}     //  84 
+    , {doBackslashD, 68 /* D */, 14,0,  TRUE}     //  85 
+    , {doBackslashG, 71 /* G */, 2,0,  TRUE}     //  86 
+    , {doProperty, 78 /* N */, 14,0,  FALSE}     //  87 
+    , {doProperty, 112 /* p */, 14,0,  FALSE}     //  88 
+    , {doProperty, 80 /* P */, 14,0,  FALSE}     //  89 
+    , {doEnterQuoteMode, 81 /* Q */, 2,0,  TRUE}     //  90 
+    , {doBackslashS, 83 /* S */, 14,0,  TRUE}     //  91 
+    , {doBackslashs, 115 /* s */, 14,0,  TRUE}     //  92 
+    , {doBackslashW, 87 /* W */, 14,0,  TRUE}     //  93 
+    , {doBackslashw, 119 /* w */, 14,0,  TRUE}     //  94 
+    , {doBackslashX, 88 /* X */, 14,0,  TRUE}     //  95 
+    , {doBackslashZ, 90 /* Z */, 2,0,  TRUE}     //  96 
+    , {doBackslashz, 122 /* z */, 2,0,  TRUE}     //  97 
+    , {doBackRef, 128, 14,0,  TRUE}     //  98 
+    , {doEscapeError, 253, 101,0,  FALSE}     //  99 
+    , {doLiteralChar, 255, 14,0,  TRUE}     //  100 
+    , {doExit, 255, 101,0,  TRUE}     //  101      errorDeath
  };
 static const char * const RegexStateNames[] = {    0,
      "start",
@@ -248,6 +249,7 @@
     0,
     0,
     0,
+    0,
      "open-paren-lookbehind",
     0,
     0,
@@ -262,6 +264,7 @@
     0,
     0,
     0,
+    0,
      "quant-star",
     0,
     0,
@@ -285,7 +288,6 @@
     0,
     0,
      "backslash",
-    0,
     0,
     0,
     0,

Index: regexcst.txt
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/regexcst.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- regexcst.txt	10 Sep 2003 02:42:24 -0000	1.1
+++ regexcst.txt	6 Apr 2004 10:08:49 -0000	1.2
@@ -135,6 +135,7 @@
     'i'                     paren-flag                              doBeginMatchMode
     'm'                     paren-flag                              doBeginMatchMode
     's'                     paren-flag                              doBeginMatchMode
+    'w'                     paren-flag                              doBeginMatchMode
     'x'                     paren-flag                              doBeginMatchMode
     '-'                     paren-flag                              doBeginMatchMode
     '('                  n  errorDeath                              doConditionalExpr
@@ -163,11 +164,12 @@
     'i'                  n  paren-flag                              doMatchMode
     'm'                  n  paren-flag                              doMatchMode
     's'                  n  paren-flag                              doMatchMode
+    'w'                  n  paren-flag                              doMatchMode
     'x'                  n  paren-flag                              doMatchMode
     '-'                  n  paren-flag                              doMatchMode
     ')'                  n  term                                    doSetMatchMode
     ':'                  n  term              ^expr-quant           doMatchModeParen
-    default                 errorDeath
+    default                 errorDeath                              doBadModeFlag
     
     
 #
@@ -248,7 +250,6 @@
    'X'                   n  expr-quant                              doBackslashX
    'Z'                   n  term                                    doBackslashZ
    'z'                   n  term                                    doBackslashz
-   '0'                   n  expr-quant                              doOctal
    digit_char	         n  expr-quant                              doBackRef         #  Will scan multiple digits
    eof                      errorDeath                              doEscapeError
    default               n  expr-quant		                    doLiteralChar     #  Escaped literal char.		       

Index: regeximp.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/regeximp.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- regeximp.h	10 Sep 2003 02:42:24 -0000	1.1
+++ regeximp.h	6 Apr 2004 10:08:49 -0000	1.2
@@ -16,38 +16,37 @@
 
 U_NAMESPACE_BEGIN
 
+#ifdef REGEX_DEBUG   /* For debugging, define REGEX_DEBUG in regex.h, not here in this file. */
 //
-//  debugging support.  Enable one or more of the #defines immediately following
+//  debugging options.  Enable one or more of the three #defines immediately following
 //
-#ifdef _DEBUG
+
 //#define REGEX_SCAN_DEBUG
-//#define REGEX_DUMP_DEBUG
-//#define REGEX_RUN_DEBUG
-#endif
+#define REGEX_DUMP_DEBUG
+#define REGEX_RUN_DEBUG
+
 //  End of #defines inteded to be directly set.
 
-#if defined(REGEX_SCAN_DEBUG) || defined(REGEX_RUN_DEBUG) || defined(REGEX_DUMP_DEBUG)
-#define REGEX_DEBUG 1
 #include <stdio.h>
 #endif
 
 #ifdef REGEX_SCAN_DEBUG
-#define REGEX_SCAN_DEBUG_PRINTF printf
+#define REGEX_SCAN_DEBUG_PRINTF(a) printf a
 #else
-#define REGEX_SCAN_DEBUG_PRINTF
+#define REGEX_SCAN_DEBUG_PRINTF(a)
 #endif
 
 #ifdef REGEX_DUMP_DEBUG
-#define REGEX_DUMP_DEBUG_PRINTF printf
+#define REGEX_DUMP_DEBUG_PRINTF(a) printf a
 #else
-#define REGEX_DUMP_DEBUG_PRINTF
+#define REGEX_DUMP_DEBUG_PRINTF(a)
 #endif
 
 #ifdef REGEX_RUN_DEBUG
-#define REGEX_RUN_DEBUG_PRINTF printf
-#define REGEX_DUMP_DEBUG_PRINTF printf
+#define REGEX_RUN_DEBUG_PRINTF(a) printf a
+#define REGEX_DUMP_DEBUG_PRINTF(a) printf a
 #else
-#define REGEX_RUN_DEBUG_PRINTF
+#define REGEX_RUN_DEBUG_PRINTF(a)
 #endif
 
 
@@ -165,10 +164,12 @@
      URX_LOOP_C        = 51,   // Continue a [set]* or OneChar* loop.
                                //   Operand is a matcher static data location.
                                //   Must always immediately follow  LOOP_x_I instruction.
-     URX_LOOP_DOT_I    = 52    // .*, initialization of the optimized loop.
+     URX_LOOP_DOT_I    = 52,   // .*, initialization of the optimized loop.
                                //   Operand value:
                                //      0:  Normal (. doesn't match new-line) mode.
                                //      1:  . matches new-line mode.
+     URX_BACKSLASH_BU  = 53    // \b or \B in UREGEX_UWORD mode, using Unicode style
+                               //   word boundaries.
 
 };           
 
@@ -227,7 +228,8 @@
         "STAT_SETREF_N",       \
         "LOOP_SR_I",           \
         "LOOP_C",              \
-        "LOOP_DOT_I"
+        "LOOP_DOT_I",          \
+        "BACKSLASH_BU"
 
 
 //

Index: rematch.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/rematch.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rematch.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ rematch.cpp	6 Apr 2004 10:08:50 -0000	1.2
@@ -18,6 +18,7 @@
 #include "unicode/uniset.h"
 #include "unicode/uchar.h"
 #include "unicode/ustring.h"
+#include "unicode/rbbi.h"
 #include "uassert.h"
 #include "cmemory.h"
 #include "uvector.h"
@@ -42,6 +43,7 @@
     fDeferredStatus    = U_ZERO_ERROR;
     fStack             = new UVector32(fDeferredStatus); 
     fData              = fSmallData;
+    fWordBreakItr      = NULL;
     if (pat==NULL) {
         fDeferredStatus = U_ILLEGAL_ARGUMENT_ERROR;
         return;
@@ -67,6 +69,7 @@
     fDeferredStatus    = U_ZERO_ERROR;
     fStack             = new UVector32(status); 
     fData              = fSmallData;
+    fWordBreakItr      = NULL;
     if (U_FAILURE(status)) {
         return;
     }
@@ -89,6 +92,7 @@
     fData              = fSmallData;
     fPatternOwned      = RegexPattern::compile(regexp, flags, pe, status);
     fPattern           = fPatternOwned;
+    fWordBreakItr      = NULL;
     if (U_FAILURE(status)) {
         return;
     }
@@ -107,7 +111,7 @@
 RegexMatcher::~RegexMatcher() {
     delete fStack;
     if (fData != fSmallData) {
-        delete fData;
+        uprv_free(fData);
         fData = NULL;
     }
     if (fPatternOwned) {
@@ -115,6 +119,9 @@
         fPatternOwned = NULL;
         fPattern = NULL;
     }
+    #if UCONFIG_NO_BREAK_ITERATION==0
+    delete fWordBreakItr;
+    #endif
 }
 
 
@@ -306,6 +313,14 @@
     }
 
     int32_t startPos = fMatchEnd;
+    if (fMatchStart == fMatchEnd && fMatch) {
+        // Previous match had zero length.  Move start position up one position
+        //  to avoid sending find() into a loop on zero-length matches.
+        if (startPos == fInput->length()) {
+            return FALSE;
+        }
+        startPos = fInput->moveIndex32(startPos, 1);
+    }
     int32_t inputLen = fInput->length();
     int32_t testLen  = inputLen - fPattern->fMinMatchLen;
     if (startPos > testLen) {
@@ -516,6 +531,11 @@
 
 
 
+//--------------------------------------------------------------------------------
+//
+//  lookingAt()
+//
+//--------------------------------------------------------------------------------
 UBool RegexMatcher::lookingAt(UErrorCode &status) {
     if (U_FAILURE(status)) {
         return FALSE;
@@ -530,7 +550,30 @@
 }
 
 
+UBool RegexMatcher::lookingAt(int32_t start, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    if (U_FAILURE(fDeferredStatus)) {
+        status = fDeferredStatus;
+        return FALSE;
+    }
+    if (start < 0 || start >= fInput->length()) {
+        status = U_INDEX_OUTOFBOUNDS_ERROR;
+        return FALSE;
+    }
+    reset();
+    MatchAt(start, status);
+    return fMatch;
+}
+
+
 
+//--------------------------------------------------------------------------------
+//
+//  matches()
+//
+//--------------------------------------------------------------------------------
 UBool RegexMatcher::matches(UErrorCode &status) {
     if (U_FAILURE(status)) {
         return FALSE;
@@ -546,6 +589,24 @@
 }
 
 
+UBool RegexMatcher::matches(int32_t start, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+    if (U_FAILURE(fDeferredStatus)) {
+        status = fDeferredStatus;
+        return FALSE;
+    }
+    if (start < 0 || start >= fInput->length()) {
+        status = U_INDEX_OUTOFBOUNDS_ERROR;
+        return FALSE;
+    }
+    reset();
+    MatchAt(start, status);
+    UBool   success  = (fMatch && fMatchEnd==fInput->length());
+    return success;
+}
+
 
 
 const RegexPattern &RegexMatcher::pattern() const {
@@ -627,27 +688,32 @@
 RegexMatcher &RegexMatcher::reset(const UnicodeString &input) {
     fInput          = &input;
     reset();
+    if (fWordBreakItr != NULL) {
+        #if UCONFIG_NO_BREAK_ITERATION==0
+        fWordBreakItr->setText(input);
+        #endif
+    }
     return *this;
 }
 
 
-
-REStackFrame *RegexMatcher::resetStack() {
-    // Discard any previous contents of the state save stack, and initialize a
-    //  new stack frame to all -1.  The -1s are needed for capture group limits, where
-    //  they indicate that a group has not yet matched anything.
-    fStack->removeAllElements();
-
-    int32_t *iFrame = fStack->reserveBlock(fPattern->fFrameSize, fDeferredStatus);
-    int i;
-    for (i=0; i<fPattern->fFrameSize; i++) {
-        iFrame[i] = -1;
+RegexMatcher &RegexMatcher::reset(int32_t position, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return *this;
     }
-    return (REStackFrame *)iFrame;
+    reset();
+    if (position < 0 || position >= fInput->length()) {
+        status = U_INDEX_OUTOFBOUNDS_ERROR;
+        return *this;
+    }
+    fMatchEnd = position;
+    return *this;
 }
 
 
 
+
+
 //--------------------------------------------------------------------------------
 //
 //    setTrace
@@ -792,6 +858,37 @@
 
 
 
+//================================================================================
+//
+//    Code following this point in this file is the internal
+//    Match Engine Implementation.
+//
+//================================================================================
+
+
+//--------------------------------------------------------------------------------
+//
+//   resetStack
+//           Discard any previous contents of the state save stack, and initialize a
+//           new stack frame to all -1.  The -1s are needed for capture group limits, 
+//           where they indicate that a group has not yet matched anything.
+//--------------------------------------------------------------------------------
+REStackFrame *RegexMatcher::resetStack() {
+    // Discard any previous contents of the state save stack, and initialize a
+    //  new stack frame to all -1.  The -1s are needed for capture group limits, where
+    //  they indicate that a group has not yet matched anything.
+    fStack->removeAllElements();
+
+    int32_t *iFrame = fStack->reserveBlock(fPattern->fFrameSize, fDeferredStatus);
+    int i;
+    for (i=0; i<fPattern->fFrameSize; i++) {
+        iFrame[i] = -1;
+    }
+    return (REStackFrame *)iFrame;
+}
+
+
+
 //--------------------------------------------------------------------------------
 //
 //   isWordBoundary 
@@ -804,9 +901,6 @@
 //                               opposite in membership in \w set
 //
 //          parameters:   pos   - the current position in the input buffer
-//                        start - the position where the match operation started.
-//                                don't backup before this position when looking back
-//                                for a preceding base char.
 //
 //--------------------------------------------------------------------------------
 UBool RegexMatcher::isWordBoundary(int32_t pos) {
@@ -847,6 +941,36 @@
 
 //--------------------------------------------------------------------------------
 //
+//   isUWordBoundary 
+//
+//         Test for a word boundary using RBBI word break.
+//
+//          parameters:   pos   - the current position in the input buffer
+//
+//--------------------------------------------------------------------------------
+UBool RegexMatcher::isUWordBoundary(int32_t pos) {
+    UBool       returnVal = FALSE;
+#if UCONFIG_NO_BREAK_ITERATION==0
+    UErrorCode  status    = U_ZERO_ERROR;  
+    
+    // If we haven't yet created a break iterator for this matcher, do it now.
+    if (fWordBreakItr == NULL) {
+        fWordBreakItr = 
+            (RuleBasedBreakIterator *)BreakIterator::createWordInstance(Locale::getEnglish(), status);
+        if (U_FAILURE(status)) {
+            // TODO:  reliable error reporting for BI failures.
+            return FALSE;
+        }
+        fWordBreakItr->setText(*fInput);
+    }
+
+    returnVal = fWordBreakItr->isBoundary(pos);
+#endif
+    return   returnVal;
+}
+
+//--------------------------------------------------------------------------------
+//
 //   StateSave      
 //       Make a new stack frame, initialized as a copy of the current stack frame.
 //       Set the pattern index in the original stack frame from the operand value
@@ -1151,6 +1275,17 @@
             break;
 
 
+        case URX_BACKSLASH_BU:          // Test for word boundaries, Unicode-style
+            {
+                UBool success = isUWordBoundary(fp->fInputIdx);
+                success ^= (opValue != 0);     // flip sense for \B
+                if (!success) {
+                    fp = (REStackFrame *)fStack->popFrame(frameSize);
+                }
+            }
+            break;
+
+
         case URX_BACKSLASH_D:            // Test for decimal digit
             {
                 if (fp->fInputIdx >= inputLen) {
@@ -1352,7 +1487,7 @@
                         break;
                     }
                 }
-            }
+            } 
             // Either at end of input, or the character wasn't in the set.
             // Either way, we need to back track out.
             fp = (REStackFrame *)fStack->popFrame(frameSize);
@@ -1639,14 +1774,7 @@
                         //   we do too.
                         break;
                     }
-                /*
-                if ((fp->fInputIdx + len > inputLen) || 
-                    u_strncmp(inputBuf+groupStartIdx, inputBuf+fp->fInputIdx, len) != 0) {
-                    fp = (REStackFrame *)fStack->popFrame(frameSize);   // FAIL, no match.
-                } else {
-                    fp->fInputIdx += len;     // Match.  Advance current input position.
-                }
-                */
+
                 UBool  haveMatch = FALSE;
                 if (fp->fInputIdx + len <= inputLen) {
                     if (opType == URX_BACKREF) {
@@ -1729,7 +1857,7 @@
                 if (u_foldCase(c, U_FOLD_CASE_DEFAULT) == opValue) {           
                     break;
                 }
-            }
+            } 
             fp = (REStackFrame *)fStack->popFrame(frameSize);
             break;
 
@@ -1747,17 +1875,18 @@
                 opValue = URX_VAL(op);
                 U_ASSERT(opType == URX_STRING_LEN);
                 stringLen = opValue;
-
+                
                 int32_t stringEndIndex = fp->fInputIdx + stringLen;
-                if (stringEndIndex <= inputLen &&
-                    u_strncasecmp(inputBuf+fp->fInputIdx, litText+stringStartIdx,
-                                  stringLen, U_FOLD_CASE_DEFAULT) == 0) {
-                    // Success.  Advance the current input position.
-                    fp->fInputIdx = stringEndIndex;
-                } else {
-                    // No match.  Back up matching to a saved state
-                    fp = (REStackFrame *)fStack->popFrame(frameSize);
-                }
+                if (stringEndIndex <= inputLen) {
+                    if (u_strncasecmp(inputBuf+fp->fInputIdx, litText+stringStartIdx,
+                        stringLen, U_FOLD_CASE_DEFAULT) == 0) {
+                        // Success.  Advance the current input position.
+                        fp->fInputIdx = stringEndIndex;
+                        break;
+                    }
+                }                 
+                // No match.  Back up matching to a saved state
+                fp = (REStackFrame *)fStack->popFrame(frameSize);
             }
             break;
 
@@ -2003,13 +2132,17 @@
             {
                 // Loop through input until the input is exhausted (we reach an end-of-line)
                 // In multi-line mode, we can just go straight to the end of the input.
-                int32_t ix = inputLen;
-                if (opValue == 0) {
+                int32_t ix;
+                if (opValue == 1) {
+                    // Multi-line mode.
+                    ix = inputLen;
+                } else {
                     // NOT multi-line mode.  Line endings do not match '.'
                     // Scan forward until a line ending or end of input.
                     ix = fp->fInputIdx;
                     for (;;) {
                         if (ix >= inputLen) {
+                            ix = inputLen;
                             break;
                         }
                         UChar32   c;
@@ -2103,13 +2236,13 @@
         fMatchStart   = startIdx;
         fMatchEnd     = fp->fInputIdx;
         if (fTraceDebug) {
-            REGEX_RUN_DEBUG_PRINTF("Match.  start=%d   end=%d\n\n", fMatchStart, fMatchEnd);
+            REGEX_RUN_DEBUG_PRINTF(("Match.  start=%d   end=%d\n\n", fMatchStart, fMatchEnd));
         }
     }
     else
     {
         if (fTraceDebug) {
-            REGEX_RUN_DEBUG_PRINTF("No match\n\n");
+            REGEX_RUN_DEBUG_PRINTF(("No match\n\n"));
         }
     }
 
@@ -2122,7 +2255,7 @@
 
 
 
-const char RegexMatcher::fgClassID = 0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegexMatcher)
 
 U_NAMESPACE_END
 

Index: remtrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/remtrans.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- remtrans.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ remtrans.cpp	6 Apr 2004 10:08:50 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -18,7 +18,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char RemoveTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RemoveTransliterator)
 
 /**
  * System registration hook.
@@ -34,8 +34,9 @@
 /**
  * Factory method
  */
-Transliterator* RemoveTransliterator::_create(const UnicodeString& ID,
+Transliterator* RemoveTransliterator::_create(const UnicodeString& /*ID*/,
                                               Token /*context*/) {
+    /* We don't need the ID or context. We just remove data */
     return new RemoveTransliterator();
 }
 

Index: remtrans.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/remtrans.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- remtrans.h	10 Sep 2003 02:42:24 -0000	1.3
+++ remtrans.h	6 Apr 2004 10:08:50 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -64,14 +64,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  private:
 
@@ -79,12 +79,6 @@
      * Factory method
      */
     static Transliterator* _create(const UnicodeString& ID, Token context);
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: repattrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/repattrn.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- repattrn.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ repattrn.cpp	6 Apr 2004 10:08:50 -0000	1.2
@@ -13,6 +13,7 @@
 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
 
 #include "unicode/regex.h"
+#include "unicode/uclean.h"
 #include "uassert.h"
 #include "uvector.h"
 #include "uvectr32.h"
@@ -28,6 +29,8 @@
 //
 //--------------------------------------------------------------------------
 RegexPattern::RegexPattern() {
+    UErrorCode status = U_ZERO_ERROR;
+    u_init(&status);
     // Init all of this instances data.
     init();
 
@@ -72,15 +75,18 @@
     fLiteralText      = other.fLiteralText;
     fDeferredStatus   = other.fDeferredStatus;
     fMinMatchLen      = other.fMinMatchLen;
+    fFrameSize        = other.fFrameSize;
+    fDataSize         = other.fDataSize;
     fMaxCaptureDigits = other.fMaxCaptureDigits;
     fStaticSets       = other.fStaticSets; 
+    fStaticSets8      = other.fStaticSets8;
     
     fStartType        = other.fStartType;
     fInitialStringIdx = other.fInitialStringIdx;
     fInitialStringLen = other.fInitialStringLen;
     *fInitialChars    = *other.fInitialChars;
-    *fInitialChars8   = *other.fInitialChars8;
     fInitialChar      = other.fInitialChar;
+    *fInitialChars8   = *other.fInitialChars8;
 
     //  Copy the pattern.  It's just values, nothing deep to copy.
     fCompiledPat->assign(*other.fCompiledPat, fDeferredStatus);
@@ -118,20 +124,26 @@
 //
 //--------------------------------------------------------------------------
 void RegexPattern::init() {
+    fPattern.remove();
     fFlags            = 0;
+    fCompiledPat      = 0;
+    fLiteralText.remove();
+    fSets             = NULL;
+    fSets8            = NULL;
     fDeferredStatus   = U_ZERO_ERROR;
     fMinMatchLen      = 0;
-    fMaxCaptureDigits = 1;  
-    fStaticSets       = NULL;
     fFrameSize        = 0;
     fDataSize         = 0;
+    fGroupMap         = NULL;
+    fMaxCaptureDigits = 1;  
+    fStaticSets       = NULL;
+    fStaticSets8      = NULL;
     fStartType        = START_NO_INFO;
     fInitialStringIdx = 0;
     fInitialStringLen = 0;
     fInitialChars     = NULL;
-    fInitialChars8    = NULL;
     fInitialChar      = 0;
-    fSets8            = NULL;
+    fInitialChars8    = NULL;
     
     fCompiledPat      = new UVector32(fDeferredStatus);
     fGroupMap         = new UVector32(fDeferredStatus);
@@ -170,14 +182,14 @@
     }
     delete fSets;
     fSets = NULL;
+    delete[] fSets8;
+    fSets8 = NULL;
     delete fGroupMap;
     fGroupMap = NULL;
     delete fInitialChars;
     fInitialChars = NULL;
     delete fInitialChars8;
     fInitialChars8 = NULL;
-    delete[] fSets8;
-    fSets8 = NULL;
 }
 
 
@@ -405,8 +417,8 @@
 //           Debugging function only.
 //
 //---------------------------------------------------------------------
-void   RegexPattern::dumpOp(int32_t index) const {
 #if defined(REGEX_DEBUG)
+void   RegexPattern::dumpOp(int32_t index) const {
     static const char * const opNames[] = {URX_OPCODE_NAMES};
     int32_t op          = fCompiledPat->elementAti(index);
     int32_t val         = URX_VAL(op);
@@ -416,7 +428,7 @@
         pinnedType = 0;
     }
     
-    REGEX_DUMP_DEBUG_PRINTF("%4d   %08x    %-15s  ", index, op, opNames[pinnedType]);
+    REGEX_DUMP_DEBUG_PRINTF(("%4d   %08x    %-15s  ", index, op, opNames[pinnedType]));
     switch (type) {
     case URX_NOP:
     case URX_DOTANY:
@@ -442,6 +454,7 @@
     case URX_JMP_SAV:
     case URX_JMP_SAV_X:
     case URX_BACKSLASH_B:
+    case URX_BACKSLASH_BU:
     case URX_BACKSLASH_D:
     case URX_BACKSLASH_Z:
     case URX_STRING_LEN:
@@ -466,12 +479,12 @@
     case URX_LOOP_C:
     case URX_LOOP_DOT_I:
         // types with an integer operand field.
-        REGEX_DUMP_DEBUG_PRINTF("%d", val);
+        REGEX_DUMP_DEBUG_PRINTF(("%d", val));
         break;
         
     case URX_ONECHAR:
     case URX_ONECHAR_I:
-        REGEX_DUMP_DEBUG_PRINTF("%c", val<256?val:'?');
+        REGEX_DUMP_DEBUG_PRINTF(("%c", val<256?val:'?'));
         break;
         
     case URX_STRING:
@@ -484,7 +497,7 @@
             for (i=val; i<val+length; i++) {
                 UChar c = fLiteralText[i];
                 if (c < 32 || c >= 256) {c = '.';}
-                REGEX_DUMP_DEBUG_PRINTF("%c", c);
+                REGEX_DUMP_DEBUG_PRINTF(("%c", c));
             }
         }
         break;
@@ -496,7 +509,7 @@
             UnicodeSet *set = (UnicodeSet *)fSets->elementAt(val);
             set->toPattern(s, TRUE);
             for (int32_t i=0; i<s.length(); i++) {
-                REGEX_DUMP_DEBUG_PRINTF("%c", s.charAt(i));
+                REGEX_DUMP_DEBUG_PRINTF(("%c", s.charAt(i)));
             }
         }
         break;
@@ -506,86 +519,86 @@
         {
             UnicodeString s;
             if (val & URX_NEG_SET) {
-                REGEX_DUMP_DEBUG_PRINTF("NOT ");
+                REGEX_DUMP_DEBUG_PRINTF(("NOT "));
                 val &= ~URX_NEG_SET;
             }
             UnicodeSet *set = fStaticSets[val];
             set->toPattern(s, TRUE);
             for (int32_t i=0; i<s.length(); i++) {
-                REGEX_DUMP_DEBUG_PRINTF("%c", s.charAt(i));
+                REGEX_DUMP_DEBUG_PRINTF(("%c", s.charAt(i)));
             }
         }
         break;
 
         
     default:
-        REGEX_DUMP_DEBUG_PRINTF("??????");
+        REGEX_DUMP_DEBUG_PRINTF(("??????"));
         break;
     }
-    REGEX_DUMP_DEBUG_PRINTF("\n");
-#endif
+    REGEX_DUMP_DEBUG_PRINTF(("\n"));
 }
+#endif
 
 
-
-void   RegexPattern::dump() const {
 #if defined(REGEX_DEBUG)
+U_CAPI void  U_EXPORT2 
+RegexPatternDump(const RegexPattern *This) {
     int      index;
     int      i;
 
-    REGEX_DUMP_DEBUG_PRINTF("Original Pattern:  ");
-    for (i=0; i<fPattern.length(); i++) {
-        REGEX_DUMP_DEBUG_PRINTF("%c", fPattern.charAt(i));
+    REGEX_DUMP_DEBUG_PRINTF(("Original Pattern:  "));
+    for (i=0; i<This->fPattern.length(); i++) {
+        REGEX_DUMP_DEBUG_PRINTF(("%c", This->fPattern.charAt(i)));
     }
-    REGEX_DUMP_DEBUG_PRINTF("\n");
-    REGEX_DUMP_DEBUG_PRINTF("   Min Match Length:  %d\n", fMinMatchLen);
-    REGEX_DUMP_DEBUG_PRINTF("   Match Start Type:  %s\n", START_OF_MATCH_STR(fStartType));   
-    if (fStartType == START_STRING) {
-        REGEX_DUMP_DEBUG_PRINTF("    Initial match sting: \"");
-        for (i=fInitialStringIdx; i<fInitialStringIdx+fInitialStringLen; i++) {
-            REGEX_DUMP_DEBUG_PRINTF("%c", fLiteralText[i]);   // TODO:  non-printables, surrogates.
+    REGEX_DUMP_DEBUG_PRINTF(("\n"));
+    REGEX_DUMP_DEBUG_PRINTF(("   Min Match Length:  %d\n", This->fMinMatchLen));
+    REGEX_DUMP_DEBUG_PRINTF(("   Match Start Type:  %s\n", START_OF_MATCH_STR(This->fStartType)));   
+    if (This->fStartType == START_STRING) {
+        REGEX_DUMP_DEBUG_PRINTF(("    Initial match sting: \""));
+        for (i=This->fInitialStringIdx; i<This->fInitialStringIdx+This->fInitialStringLen; i++) {
+            REGEX_DUMP_DEBUG_PRINTF(("%c", This->fLiteralText[i]));   // TODO:  non-printables, surrogates.
         }
 
-    } else if (fStartType == START_SET) {
-        int32_t numSetChars = fInitialChars->size();
+    } else if (This->fStartType == START_SET) {
+        int32_t numSetChars = This->fInitialChars->size();
         if (numSetChars > 20) {
             numSetChars = 20;
         }
-        REGEX_DUMP_DEBUG_PRINTF("     Match First Chars : ");
+        REGEX_DUMP_DEBUG_PRINTF(("     Match First Chars : "));
         for (i=0; i<numSetChars; i++) {
-            UChar32 c = fInitialChars->charAt(i);
+            UChar32 c = This->fInitialChars->charAt(i);
             if (0x20<c && c <0x7e) { 
-                REGEX_DUMP_DEBUG_PRINTF("%c ", c);
+                REGEX_DUMP_DEBUG_PRINTF(("%c ", c));
             } else {
-                REGEX_DUMP_DEBUG_PRINTF("%#x ", c);
+                REGEX_DUMP_DEBUG_PRINTF(("%#x ", c));
             }
         }
-        if (numSetChars < fInitialChars->size()) {
-            REGEX_DUMP_DEBUG_PRINTF(" ...");
+        if (numSetChars < This->fInitialChars->size()) {
+            REGEX_DUMP_DEBUG_PRINTF((" ..."));
         }
-        REGEX_DUMP_DEBUG_PRINTF("\n");
+        REGEX_DUMP_DEBUG_PRINTF(("\n"));
 
-    } else if (fStartType == START_CHAR) {
-        REGEX_DUMP_DEBUG_PRINTF("    First char of Match : ");
-        if (0x20 < fInitialChar && fInitialChar<0x7e) {
-                REGEX_DUMP_DEBUG_PRINTF("%c\n", fInitialChar);
+    } else if (This->fStartType == START_CHAR) {
+        REGEX_DUMP_DEBUG_PRINTF(("    First char of Match : "));
+        if (0x20 < This->fInitialChar && This->fInitialChar<0x7e) {
+                REGEX_DUMP_DEBUG_PRINTF(("%c\n", This->fInitialChar));
             } else {
-                REGEX_DUMP_DEBUG_PRINTF("%#x\n", fInitialChar);
+                REGEX_DUMP_DEBUG_PRINTF(("%#x\n", This->fInitialChar));
             }
     }
 
-    REGEX_DUMP_DEBUG_PRINTF("\nIndex   Binary     Type             Operand\n"
-           "-------------------------------------------\n");
-    for (index = 0; index<fCompiledPat->size(); index++) {
-        dumpOp(index);
+    REGEX_DUMP_DEBUG_PRINTF(("\nIndex   Binary     Type             Operand\n" \
+           "-------------------------------------------\n"));
+    for (index = 0; index<This->fCompiledPat->size(); index++) {
+        This->dumpOp(index);
     }
-    REGEX_DUMP_DEBUG_PRINTF("\n\n");
-#endif
+    REGEX_DUMP_DEBUG_PRINTF(("\n\n"));
 };
+#endif
 
 
 
-const char RegexPattern::fgClassID = 0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegexPattern)
 
 //----------------------------------------------------------------------------------
 //

Index: simpletz.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/simpletz.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- simpletz.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ simpletz.cpp	6 Apr 2004 10:08:50 -0000	1.4
@@ -27,17 +27,16 @@
 
 #include "unicode/simpletz.h"
 #include "unicode/gregocal.h"
-#include "tzdat.h"
 
 U_NAMESPACE_BEGIN
 
-const char SimpleTimeZone::fgClassID = 0; // Value is irrelevant
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleTimeZone)
 
 // WARNING: assumes that no rule is measured from the end of February,
 // since we don't handle leap years. Could handle assuming always
 // Gregorian, since we know they didn't have daylight time when
 // Gregorian calendar started.
-const int8_t SimpleTimeZone::staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+const int8_t SimpleTimeZone::STATICMONTHLENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31};
 
 // *****************************************************************************
 // class SimpleTimeZone
@@ -122,40 +121,6 @@
 }
 
 /**
- * Construct from memory-mapped data.  For private use by TimeZone.
- */
-SimpleTimeZone::SimpleTimeZone(const StandardZone& stdZone,
-                               const UnicodeString& ID)
-:   TimeZone(ID)
-{
-    UErrorCode status = U_ZERO_ERROR;
-    construct(stdZone.gmtOffset,
-              0, 0, 0, 0, WALL_TIME,
-              0, 0, 0, 0, WALL_TIME,
-              0, status);
-}
-
-/**
- * Construct from memory-mapped data.  For private use by TimeZone.
- */
-SimpleTimeZone::SimpleTimeZone(const DSTZone& dstZone,
-                               const UnicodeString& ID)
-:   TimeZone(ID)
-{
-    UErrorCode status = U_ZERO_ERROR;
-    construct(dstZone.gmtOffset,
-              dstZone.onsetRule.month, dstZone.onsetRule.dowim,
-              dstZone.onsetRule.dow,
-              dstZone.onsetRule.time * (int32_t)60000,
-              (TimeMode)dstZone.onsetRule.mode,
-              dstZone.ceaseRule.month, dstZone.ceaseRule.dowim,
-              dstZone.ceaseRule.dow,
-              dstZone.ceaseRule.time * (int32_t)60000,
-              (TimeMode)dstZone.ceaseRule.mode,
-              dstZone.dstSavings * (int32_t)60000, status);
-}
-
-/**
  * Internal construction method.
  */
 void SimpleTimeZone::construct(int32_t rawOffsetGMT,
@@ -403,7 +368,7 @@
 SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
                           uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const
 {
-    // Check the month before indexing into staticMonthLength. This
+    // Check the month before indexing into STATICMONTHLENGTH. This
     // duplicates the test that occurs in the 7-argument getOffset(),
     // however, this is unavoidable. We don't mind because this method, in
     // fact, should not be called; internal code should always call the
@@ -415,14 +380,14 @@
         return 0;
     }
 
-    return getOffset(era, year, month, day, dayOfWeek, millis, staticMonthLength[month], status);
+    return getOffset(era, year, month, day, dayOfWeek, millis, STATICMONTHLENGTH[month], status);
 }
 
 int32_t 
 SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
                           uint8_t dayOfWeek, int32_t millis, 
                           int32_t monthLength, UErrorCode& status) const {
-    // Check the month before indexing into staticMonthLength. This
+    // Check the month before indexing into STATICMONTHLENGTH. This
     // duplicates a test that occurs in the 9-argument getOffset(),
     // however, this is unavoidable. We don't mind because this method, in
     // fact, should not be called; internal code should always call the
@@ -436,7 +401,7 @@
     }
 
     // TODO FIX We don't handle leap years yet!
-    int32_t prevMonthLength = (month >= 1) ? staticMonthLength[month - 1] : 31;
+    int32_t prevMonthLength = (month >= 1) ? STATICMONTHLENGTH[month - 1] : 31;
 
     return getOffset(era, year, month, day, dayOfWeek, millis,
                      monthLength, prevMonthLength, status);
@@ -460,7 +425,9 @@
         || millis < 0
         || millis >= U_MILLIS_PER_DAY
         || monthLength < 28
-        || monthLength > 31) {
+        || monthLength > 31
+        || prevMonthLength < 28
+        || prevMonthLength > 31) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return -1;
     }
@@ -579,7 +546,7 @@
         
         // if ruleDay is negative (we assume it's not zero here), we have to do
         // the same calculation figuring backward from the last day of the month.
-        // (staticMonthLength gives us that last day.  We don't take leap years
+        // (STATICMONTHLENGTH gives us that last day.  We don't take leap years
         // into account, so this may not work right for February.)
         else
         {
@@ -855,7 +822,7 @@
                 status = U_ILLEGAL_ARGUMENT_ERROR;
                 return;
             }
-        } else if (startDay > staticMonthLength[startMonth]) {
+        } else if (startDay > STATICMONTHLENGTH[startMonth]) {
             status = U_ILLEGAL_ARGUMENT_ERROR;
             return;
         }
@@ -910,7 +877,7 @@
                 status = U_ILLEGAL_ARGUMENT_ERROR;
                 return;
             }
-        } else if (endDay > staticMonthLength[endMonth]) {
+        } else if (endDay > STATICMONTHLENGTH[endMonth]) {
             status = U_ILLEGAL_ARGUMENT_ERROR;
             return;
         }

Index: smpdtfmt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/smpdtfmt.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- smpdtfmt.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ smpdtfmt.cpp	6 Apr 2004 10:08:50 -0000	1.4
@@ -40,24 +40,32 @@
 #include "unicode/uchar.h"
 #include "unicode/ustring.h"
 #include "uprops.h"
+#include "cstring.h"
 #include <float.h>
 
+#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
+#include <stdio.h>
+#endif
+
 // *****************************************************************************
 // class SimpleDateFormat
 // *****************************************************************************
 
 U_NAMESPACE_BEGIN
 
+/**
+ * Last-resort string to use for "GMT" when constructing time zone strings.
+ */
 // For time zones that have no names, use strings GMT+minutes and
 // GMT-minutes. For instance, in France the time zone is GMT+60.
 // Also accepted are GMT+H:MM or GMT-H:MM.
-const UChar SimpleDateFormat::fgGmt[]      = {0x0047, 0x004D, 0x0054, 0x0000};         // "GMT"
-const UChar SimpleDateFormat::fgGmtPlus[]  = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+"
-const UChar SimpleDateFormat::fgGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-"
+static const UChar gGmt[]      = {0x0047, 0x004D, 0x0054, 0x0000};         // "GMT"
+static const UChar gGmtPlus[]  = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+"
+static const UChar gGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-"
 
 // This is a pattern-of-last-resort used when we can't load a usable pattern out
 // of a resource.
-const UChar SimpleDateFormat::fgDefaultPattern[] =
+static const UChar gDefaultPattern[] =
 {
     0x79, 0x79, 0x79, 0x79, 0x4D, 0x4D, 0x64, 0x64, 0x20, 0x68, 0x68, 0x3A, 0x6D, 0x6D, 0x20, 0x61, 0
 };  /* "yyyyMMdd hh:mm a" */
@@ -71,15 +79,9 @@
  * These are the tags we expect to see in normal resource bundle files associated
  * with a locale.
  */
-const char SimpleDateFormat::fgDateTimePatternsTag[]="DateTimePatterns";
-
-const char      SimpleDateFormat::fgClassID = 0; // Value is irrelevant
+static const char gDateTimePatternsTag[]="DateTimePatterns";
 
-/**
- * This value of defaultCenturyStart indicates that the system default is to be
- * used.  To be removed in 2.8
- */
-const UDate     SimpleDateFormat::fgSystemDefaultCentury        = DBL_MIN;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
 
 static const UChar QUOTE = 0x27; // Single quote
 
@@ -179,7 +181,7 @@
  */
 SimpleDateFormat::SimpleDateFormat(const Locale& locale,
                                    UErrorCode& status)
-:   fPattern(fgDefaultPattern),
+:   fPattern(gDefaultPattern),
     fLocale(locale),
     fSymbols(NULL)
 {
@@ -281,7 +283,7 @@
     initializeCalendar(NULL, locale, status);
 
     // use Date Format Symbols' helper function to do the actual load.
-    ResourceBundle dateTimePatterns = DateFormatSymbols::getData(resources, fgDateTimePatternsTag, fCalendar?fCalendar->getType():NULL,  status);
+    ResourceBundle dateTimePatterns = DateFormatSymbols::getData(resources, gDateTimePatternsTag, fCalendar?fCalendar->getType():NULL,  status);
     if (U_FAILURE(status)) return;
 
     if (dateTimePatterns.getSize() <= kDateTime)
@@ -290,6 +292,8 @@
         return;
     }
 
+    setLocales(dateTimePatterns);
+
     // create a symbols object from the locale
     initializeSymbols(locale,fCalendar, status);
     if (U_FAILURE(status)) return;
@@ -531,7 +535,8 @@
     UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH, 
     UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, 
     UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET,
-    UCAL_YEAR_WOY, UCAL_DOW_LOCAL
+    UCAL_YEAR_WOY, UCAL_DOW_LOCAL,UCAL_EXTENDED_YEAR,
+    UCAL_JULIAN_DAY,UCAL_MILLISECONDS_IN_DAY
 };
 
 // Map index into pattern character string to DateFormat field number
@@ -546,7 +551,8 @@
     DateFormat::kWeekOfMonthField, DateFormat::kAmPmField,
     DateFormat::kHour1Field, DateFormat::kHour0Field,
     DateFormat::kTimezoneField, DateFormat::kYearWOYField, 
-    DateFormat::kDOWLocalField
+    DateFormat::kDOWLocalField, DateFormat::kExtendedYearField,
+    DateFormat::kJulianDayField, DateFormat::kMillisecondsInDayField
 };
 
 
@@ -560,6 +566,10 @@
                             Calendar& cal,
                             UErrorCode& status) const
 {
+    if (U_FAILURE(status)) {
+        return;
+    }
+
     // this function gets called by format() to produce the appropriate substitution
     // text for an individual pattern symbol (e.g., "HH" or "yyyy")
 
@@ -572,6 +582,7 @@
     if (patternCharPtr == NULL)
     {
         status = U_INVALID_FORMAT_ERROR;
+        return;
     }
 
     patternCharIndex = (EField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
@@ -667,11 +678,11 @@
                     cal.get(UCAL_DST_OFFSET, status);
 
             if (value < 0) {
-                appendTo += fgGmtMinus;
+                appendTo += gGmtMinus;
                 value = -value; // suppress the '-' sign for text display.
             }
             else
-                appendTo += fgGmtPlus;
+                appendTo += gGmtPlus;
             
             zeroPaddingNumber(appendTo, (int32_t)(value/U_MILLIS_PER_HOUR), 2, 2);
             appendTo += (UChar)0x003A /*':'*/;
@@ -1071,6 +1082,10 @@
     UnicodeString temp;
     UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
 
+#if defined (U_DEBUG_CAL)
+    //fprintf(stderr, "%s:%d - [%c]  st=%d \n", __FILE__, __LINE__, (char) ch, start);
+#endif
+
     if (patternCharPtr == NULL) {
         return -start;
     }
@@ -1224,7 +1239,7 @@
         // characters of GMT+/-HH:MM etc.
 
         UnicodeString lcaseText(text);
-        UnicodeString lcaseGMT(fgGmt);
+        UnicodeString lcaseGMT(gGmt);
         int32_t sign = 0;
         int32_t offset;
         int32_t gmtLen = lcaseGMT.length();
@@ -1325,14 +1340,14 @@
             // a little more permissive than RFC 822.  It will try to do
             // its best with numbers that aren't strictly 4 digits long.
             UErrorCode status = U_ZERO_ERROR;
-            DecimalFormat *fmt = new DecimalFormat("+####;-####", status);
+            DecimalFormat fmt("+####;-####", status);
             if(U_FAILURE(status))
                 return -start;
-            fmt->setParseIntegerOnly(TRUE);
+            fmt.setParseIntegerOnly(TRUE);
             // WORK AROUND BUG IN NUMBER FORMAT IN 1.2B3
             int32_t parseStart = pos.getIndex();
             Formattable tzNumber;
-            fmt->parse( text, tzNumber, pos );
+            fmt.parse( text, tzNumber, pos );
             if( pos.getIndex() == parseStart) {
                 // WORK AROUND BUG IN NUMBER FORMAT IN 1.2B3
                 return -start;   // Wasn't actually a number.
@@ -1548,7 +1563,6 @@
   initializeSymbols(fLocale, fCalendar, status);  // we need new symbols
   initializeDefaultCentury();  // we need a new century (possibly)
 }
-
 
 U_NAMESPACE_END
 

Index: sortkey.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/sortkey.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- sortkey.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ sortkey.cpp	6 Apr 2004 10:08:50 -0000	1.4
@@ -43,7 +43,7 @@
 #define kInvalidHashCode ((int32_t)0)
 #define kEmptyHashCode ((int32_t)1)
 
-const char CollationKey::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationKey)
 
 CollationKey::CollationKey()
     : UObject(), fBogus(FALSE), fCount(0), fCapacity(0),

Index: strmatch.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/strmatch.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- strmatch.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ strmatch.cpp	6 Apr 2004 10:08:50 -0000	1.5
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2001, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 2001-2003, International Business Machines Corporation and others. All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
 *   07/23/01    aliu        Creation.
@@ -19,7 +19,7 @@
 
 const UChar EMPTY[] = { 0 }; // empty string: ""
 
-const char StringMatcher::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringMatcher)
 
 StringMatcher::StringMatcher(const UnicodeString& theString,
                              int32_t start,
@@ -35,7 +35,9 @@
 }
 
 StringMatcher::StringMatcher(const StringMatcher& o) :
+    UnicodeFunctor(o),
     UnicodeMatcher(o),
+    UnicodeReplacer(o),
     pattern(o.pattern),
     data(o.data),
     segmentNumber(o.segmentNumber),
@@ -193,13 +195,13 @@
 void StringMatcher::addMatchSetTo(UnicodeSet& toUnionTo) const {
     UChar32 ch;
     for (int32_t i=0; i<pattern.length(); i+=UTF_CHAR_LENGTH(ch)) {
-	ch = pattern.char32At(i);
-	const UnicodeMatcher* matcher = data->lookupMatcher(ch);
-	if (matcher == NULL) {
-	    toUnionTo.add(ch);
-	} else {
-	    matcher->addMatchSetTo(toUnionTo);
-	}
+        ch = pattern.char32At(i);
+        const UnicodeMatcher* matcher = data->lookupMatcher(ch);
+        if (matcher == NULL) {
+            toUnionTo.add(ch);
+        } else {
+            matcher->addMatchSetTo(toUnionTo);
+        }
     }
 }
 
@@ -209,7 +211,7 @@
 int32_t StringMatcher::replace(Replaceable& text,
                                int32_t start,
                                int32_t limit,
-                               int32_t& cursor) {
+                               int32_t& /*cursor*/) {
     
     int32_t outLen = 0;
     
@@ -233,7 +235,7 @@
  * UnicodeReplacer API
  */
 UnicodeString& StringMatcher::toReplacerPattern(UnicodeString& rule,
-                                                UBool escapeUnprintable) const {
+                                                UBool /*escapeUnprintable*/) const {
     // assert(segmentNumber > 0);
     rule.truncate(0);
     rule.append((UChar)0x0024 /*$*/);
@@ -254,7 +256,7 @@
  * into the given set.
  * @param toUnionTo the set into which to union the output characters
  */
-void StringMatcher::addReplacementSetTo(UnicodeSet& toUnionTo) const {
+void StringMatcher::addReplacementSetTo(UnicodeSet& /*toUnionTo*/) const {
     // The output of this replacer varies; it is the source text between
     // matchStart and matchLimit.  Since this varies depending on the
     // input text, we can't compute it here.  We can either do nothing

Index: strmatch.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/strmatch.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- strmatch.h	10 Sep 2003 02:42:24 -0000	1.4
+++ strmatch.h	6 Apr 2004 10:08:50 -0000	1.5
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2001, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 2001-2003, International Business Machines Corporation and others. All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
 *   07/23/01    aliu        Creation.
@@ -198,14 +198,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
     /**
      * Union the set of all characters that may output by this object
@@ -244,11 +244,6 @@
      */
     int32_t matchLimit;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: strrepl.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/strrepl.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- strrepl.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ strrepl.cpp	6 Apr 2004 10:08:50 -0000	1.2
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002, International Business Machines Corporation
+*   Copyright (c) 2002-2003, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -21,7 +21,8 @@
 
 const UChar EMPTY[] = { 0 }; // empty string: ""
 
-const char StringReplacer::fgClassID=0;
+UnicodeReplacer::~UnicodeReplacer() {}
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringReplacer)
 
 /**
  * Construct a StringReplacer that sets the emits the given output
@@ -65,7 +66,10 @@
 /**
  * Copy constructor.
  */
-StringReplacer::StringReplacer(const StringReplacer& other) {
+StringReplacer::StringReplacer(const StringReplacer& other) :
+    UnicodeFunctor(other),
+    UnicodeReplacer(other)
+{
     output = other.output;
     cursorPos = other.cursorPos;
     hasCursor = other.hasCursor;

Index: strrepl.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/strrepl.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- strrepl.h	10 Sep 2003 02:42:24 -0000	1.1
+++ strrepl.h	6 Apr 2004 10:08:50 -0000	1.2
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002, International Business Machines Corporation
+*   Copyright (c) 2002-2003, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -67,12 +67,6 @@
      */
     const TransliterationRuleData* data;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
  public:
 
     /**
@@ -148,18 +142,18 @@
     virtual void setData(const TransliterationRuleData*);
 
     /**
-     * ICU "poor man's RTTI", returns a UClassID for the actual class.
+     * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    static UClassID getStaticClassID();
 
     /**
-     * ICU "poor man's RTTI", returns a UClassID for this class.
+     * ICU "poor man's RTTI", returns a UClassID for the actual class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    virtual UClassID getDynamicClassID() const;
 };
 
 U_NAMESPACE_END

Index: stsearch.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/stsearch.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- stsearch.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ stsearch.cpp	6 Apr 2004 10:08:50 -0000	1.5
@@ -17,7 +17,7 @@
 
 U_NAMESPACE_BEGIN
 
-const char StringSearch::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringSearch)
 
 // public constructors and destructors -----------------------------------
 
@@ -212,6 +212,11 @@
     }
 }
 
+StringSearch *
+StringSearch::clone() const {
+    return new StringSearch(*this);
+}
+
 // operator overloading ---------------------------------------------
 StringSearch & StringSearch::operator=(const StringSearch &that)
 {
@@ -364,6 +369,16 @@
                 setMatchNotFound();
                 return USEARCH_DONE;
             }
+            if (m_search_->matchedLength <= 0) {
+                // the flipping direction issue has already been handled 
+                // in next()
+                // for boundary check purposes. this will ensure that the
+                // next match will not preceed the current offset
+                // note search->matchedIndex will always be set to something
+                // in the code
+                m_search_->matchedIndex = position - 1;
+            }
+
 			ucol_setOffset(m_strsrch_->textIter, position, &status);
             while (TRUE) {
                 if (m_search_->isCanonicalMatch) {
@@ -385,14 +400,14 @@
                                                   m_search_->matchedLength))
 #endif
                 ) {
-					if (m_search_->matchedIndex == USEARCH_DONE) {
-						ucol_setOffset(m_strsrch_->textIter, 
-							           m_search_->textLength, &status);
-					}
-					else {
-						ucol_setOffset(m_strsrch_->textIter, 
-							           m_search_->matchedIndex, &status);
-					}
+                    if (m_search_->matchedIndex == USEARCH_DONE) {
+                        ucol_setOffset(m_strsrch_->textIter, 
+                                       m_search_->textLength, &status);
+                    }
+                    else {
+                        ucol_setOffset(m_strsrch_->textIter, 
+                                       m_search_->matchedIndex, &status);
+                    }
                     return m_search_->matchedIndex;
                 }
             }

Index: tblcoll.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/tblcoll.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- tblcoll.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ tblcoll.cpp	6 Apr 2004 10:08:51 -0000	1.4
@@ -75,79 +75,79 @@
 /**
 * Copy constructor, aliasing, not write-through
 */
-RuleBasedCollator::RuleBasedCollator(const RuleBasedCollator& that) 
-   : Collator(that)
-   , dataIsOwned(FALSE)
-   , isWriteThroughAlias(FALSE)
-   , ucollator(that.ucollator)
-   , urulestring(that.urulestring)
+RuleBasedCollator::RuleBasedCollator(const RuleBasedCollator& that)
+: Collator(that)
+, dataIsOwned(FALSE)
+, isWriteThroughAlias(FALSE)
+, ucollator(that.ucollator)
+, urulestring(that.urulestring)
 {
 }
 
 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
-                                           UErrorCode& status) :
-                                           dataIsOwned(FALSE)
+                                     UErrorCode& status) :
+dataIsOwned(FALSE)
 {
-  construct(rules,
-            UCOL_DEFAULT_STRENGTH,
-            UCOL_DEFAULT,
-            status);
+    construct(rules,
+        UCOL_DEFAULT_STRENGTH,
+        UCOL_DEFAULT,
+        status);
 }
 
 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
-                      ECollationStrength collationStrength,
-                      UErrorCode& status) : dataIsOwned(FALSE)
+                                     ECollationStrength collationStrength,
+                                     UErrorCode& status) : dataIsOwned(FALSE)
 {
-  construct(rules,
-            getUCollationStrength(collationStrength),
-            UCOL_DEFAULT,
-            status);
+    construct(rules,
+        getUCollationStrength(collationStrength),
+        UCOL_DEFAULT,
+        status);
 }
 
 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
                                      UColAttributeValue decompositionMode,
                                      UErrorCode& status) :
-                                     dataIsOwned(FALSE)
+dataIsOwned(FALSE)
 {
-  construct(rules,
-            UCOL_DEFAULT_STRENGTH,
-            decompositionMode,
-            status);
+    construct(rules,
+        UCOL_DEFAULT_STRENGTH,
+        decompositionMode,
+        status);
 }
 
 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
-                      ECollationStrength collationStrength,
-                      UColAttributeValue decompositionMode,
-                      UErrorCode& status) : dataIsOwned(FALSE)
+                                     ECollationStrength collationStrength,
+                                     UColAttributeValue decompositionMode,
+                                     UErrorCode& status) : dataIsOwned(FALSE)
 {
-  construct(rules,
-            getUCollationStrength(collationStrength),
-            decompositionMode,
-            status);
+    construct(rules,
+        getUCollationStrength(collationStrength),
+        decompositionMode,
+        status);
 }
 
 void
 RuleBasedCollator::setRuleStringFromCollator(UErrorCode& status)
 {
-  urulestring = NULL;
-  if (U_SUCCESS(status))
-  {
-    int32_t length;
-    const UChar *r = ucol_getRules(ucollator, &length);
-  
-	if (length > 0) {
-        // alias the rules string
-        urulestring = new UnicodeString(TRUE, r, length);
-    }
-    else {
-        urulestring = new UnicodeString();
-    }
-    /* test for NULL */
-    if (urulestring == 0) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        return;
+    urulestring = NULL;
+    if (U_SUCCESS(status))
+    {
+        int32_t length;
+        const UChar *r = ucol_getRules(ucollator, &length);
+
+        if (length > 0) {
+            // alias the rules string
+            urulestring = new UnicodeString(TRUE, r, length);
+        }
+        else {
+            urulestring = new UnicodeString();
+        }
+        /* test for NULL */
+        if (urulestring == 0) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+            return;
+        }
     }
-  }
 }
 
 // not aliasing, not write-through
@@ -157,28 +157,28 @@
                              UColAttributeValue decompositionMode,
                              UErrorCode& status)
 {
-  urulestring = 0;
-  ucollator = ucol_openRules(rules.getBuffer(), rules.length(),
-                             decompositionMode, collationStrength,
-                             NULL, &status);
+    urulestring = 0;
+    ucollator = ucol_openRules(rules.getBuffer(), rules.length(),
+        decompositionMode, collationStrength,
+        NULL, &status);
 
-  dataIsOwned = TRUE; // since we own a collator now, we need to get rid of it
-  isWriteThroughAlias = FALSE;
+    dataIsOwned = TRUE; // since we own a collator now, we need to get rid of it
+    isWriteThroughAlias = FALSE;
 
-  setRuleStringFromCollator(status);
+    setRuleStringFromCollator(status);
 }
 
 /* RuleBasedCollator public destructor ----------------------------------- */
 
 RuleBasedCollator::~RuleBasedCollator()
 {
-  if (dataIsOwned)
-  {
-    ucol_close(ucollator);
-    delete urulestring;
-  }
-  ucollator = 0;
-  urulestring = 0;
+    if (dataIsOwned)
+    {
+        ucol_close(ucollator);
+        delete urulestring;
+    }
+    ucollator = 0;
+    urulestring = 0;
 }
 
 /* RuleBaseCollator public methods --------------------------------------- */
@@ -207,24 +207,29 @@
   */
 }
 
+UBool RuleBasedCollator::operator!=(const Collator& other) const
+{
+    return !(*this == other);
+}
+
 // aliasing, not write-through
 RuleBasedCollator& RuleBasedCollator::operator=(const RuleBasedCollator& that)
 {
-  if (this != &that)
-  {
-    if (dataIsOwned)
+    if (this != &that)
     {
-      ucol_close(ucollator);
-      ucollator = NULL;
-      delete urulestring;
-    }
+        if (dataIsOwned)
+        {
+            ucol_close(ucollator);
+            ucollator = NULL;
+            delete urulestring;
+        }
 
-    dataIsOwned = FALSE;
-	isWriteThroughAlias = FALSE;
-    ucollator = that.ucollator;
-    urulestring = that.urulestring;
-  }
-  return *this;
+        dataIsOwned = FALSE;
+        isWriteThroughAlias = FALSE;
+        ucollator = that.ucollator;
+        urulestring = that.urulestring;
+    }
+    return *this;
 }
 
 // aliasing, not write-through
@@ -236,15 +241,15 @@
 CollationElementIterator* RuleBasedCollator::createCollationElementIterator
                                            (const UnicodeString& source) const
 {
-  UErrorCode status = U_ZERO_ERROR;
-  CollationElementIterator *result = new CollationElementIterator(source, this,
-                                                                  status);
-  if (U_FAILURE(status)) {
-    delete result;
-    return NULL;
-  }
+    UErrorCode status = U_ZERO_ERROR;
+    CollationElementIterator *result = new CollationElementIterator(source, this,
+                                                                    status);
+    if (U_FAILURE(status)) {
+        delete result;
+        return NULL;
+    }
 
-  return result;
+    return result;
 }
 
 /**
@@ -255,16 +260,16 @@
 CollationElementIterator* RuleBasedCollator::createCollationElementIterator
                                        (const CharacterIterator& source) const
 {
-  UErrorCode status = U_ZERO_ERROR;
-  CollationElementIterator *result = new CollationElementIterator(source, this,
-                                                                  status);
+    UErrorCode status = U_ZERO_ERROR;
+    CollationElementIterator *result = new CollationElementIterator(source, this,
+                                                                    status);
 
-  if (U_FAILURE(status)) {
-    delete result;
-    return NULL;
-  }
+    if (U_FAILURE(status)) {
+        delete result;
+        return NULL;
+    }
 
-  return result;
+    return result;
 }
 
 /**
@@ -286,11 +291,11 @@
     if (rulesize > 0) {
         UChar *rules = (UChar*) uprv_malloc( sizeof(UChar) * (rulesize) );
         if(rules != NULL) {
-          ucol_getRulesEx(ucollator, delta, rules, rulesize);
-          buffer.setTo(rules, rulesize);
-          uprv_free(rules);
+            ucol_getRulesEx(ucollator, delta, rules, rulesize);
+            buffer.setTo(rules, rulesize);
+            uprv_free(rules);
         } else { // couldn't allocate 
-          buffer.remove();
+            buffer.remove();
         }
     }
     else {
@@ -301,10 +306,10 @@
 UnicodeSet *
 RuleBasedCollator::getTailoredSet(UErrorCode &status) const
 {
-  if(U_FAILURE(status)) {
-    return NULL;
-  }
-  return (UnicodeSet *)ucol_getTailoredSet(this->ucollator, &status);
+    if(U_FAILURE(status)) {
+        return NULL;
+    }
+    return (UnicodeSet *)ucol_getTailoredSet(this->ucollator, &status);
 }
 
 
@@ -320,17 +325,17 @@
                                                const UnicodeString& target,
                                                int32_t length) const
 {
-  UErrorCode status = U_ZERO_ERROR;
-  return getEComparisonResult(compare(source.getBuffer(), uprv_min(length,source.length()), target.getBuffer(), uprv_min(length,target.length()), status));
+    UErrorCode status = U_ZERO_ERROR;
+    return getEComparisonResult(compare(source.getBuffer(), uprv_min(length,source.length()), target.getBuffer(), uprv_min(length,target.length()), status));
 }
 
 UCollationResult RuleBasedCollator::compare(
                                                const UnicodeString& source,
                                                const UnicodeString& target,
-                                               int32_t length, 
+                                               int32_t length,
                                                UErrorCode &status) const
 {
-  return compare(source.getBuffer(), uprv_min(length,source.length()), target.getBuffer(), uprv_min(length,target.length()), status);
+    return compare(source.getBuffer(), uprv_min(length,source.length()), target.getBuffer(), uprv_min(length,target.length()), status);
 }
 
 Collator::EComparisonResult RuleBasedCollator::compare(const UChar* source,
@@ -339,21 +344,21 @@
                                                        int32_t targetLength)
                                                        const
 {
-  return  getEComparisonResult(ucol_strcoll(ucollator, source, sourceLength,
-                                                     target, targetLength));
+    return  getEComparisonResult(ucol_strcoll(ucollator, source, sourceLength,
+                                                         target, targetLength));
 }
 
 UCollationResult RuleBasedCollator::compare(const UChar* source,
                                                        int32_t sourceLength,
                                                        const UChar* target,
-                                                       int32_t targetLength, 
+                                                       int32_t targetLength,
                                                        UErrorCode &status) const
 {
-  if(U_SUCCESS(status)) {
-    return  ucol_strcoll(ucollator, source, sourceLength, target, targetLength);
-  } else {
-    return UCOL_EQUAL;
-  }
+    if(U_SUCCESS(status)) {
+        return  ucol_strcoll(ucollator, source, sourceLength, target, targetLength);
+    } else {
+        return UCOL_EQUAL;
+    }
 }
 
 /**
@@ -363,21 +368,21 @@
                                              const UnicodeString& source,
                                              const UnicodeString& target) const
 {
-  return getEComparisonResult(ucol_strcoll(ucollator, source.getBuffer(), source.length(), 
-                                                      target.getBuffer(), target.length()));
+    return getEComparisonResult(ucol_strcoll(ucollator, source.getBuffer(), source.length(),
+                                                        target.getBuffer(), target.length()));
 }
 
 UCollationResult RuleBasedCollator::compare(
                                              const UnicodeString& source,
-                                             const UnicodeString& target, 
+                                             const UnicodeString& target,
                                              UErrorCode &status) const
 {
-  if(U_SUCCESS(status)) {
-    return ucol_strcoll(ucollator, source.getBuffer(), source.length(), 
-			target.getBuffer(), target.length());
-  } else {
-    return UCOL_EQUAL;
-  }
+    if(U_SUCCESS(status)) {
+        return ucol_strcoll(ucollator, source.getBuffer(), source.length(),
+                                       target.getBuffer(), target.length());
+    } else {
+        return UCOL_EQUAL;
+    }
 }
 
 /**
@@ -418,7 +423,7 @@
                                                   CollationKey& sortkey,
                                                   UErrorCode& status) const
 {
-  return getCollationKey(source.getBuffer(), source.length(), sortkey, status);
+    return getCollationKey(source.getBuffer(), source.length(), sortkey, status);
 }
 
 CollationKey& RuleBasedCollator::getCollationKey(const UChar* source,
@@ -426,22 +431,22 @@
                                                     CollationKey& sortkey,
                                                     UErrorCode& status) const
 {
-  if (U_FAILURE(status))
-  {
-    return sortkey.setToBogus();
-  }
+    if (U_FAILURE(status))
+    {
+        return sortkey.setToBogus();
+    }
 
-  if ((!source) || (sourceLen == 0)) {
-    return sortkey.reset();
-  }
+    if ((!source) || (sourceLen == 0)) {
+        return sortkey.reset();
+    }
 
-  uint8_t *result;
-  int32_t resultLen = ucol_getSortKeyWithAllocation(ucollator,
-                                                    source, sourceLen,
-                                                    &result,
-                                                    &status);
-  sortkey.adopt(result, resultLen);
-  return sortkey;
+    uint8_t *result;
+    int32_t resultLen = ucol_getSortKeyWithAllocation(ucollator,
+                                                      source, sourceLen,
+                                                      &result,
+                                                      &status);
+    sortkey.adopt(result, resultLen);
+    return sortkey;
 }
 
 /**
@@ -455,48 +460,48 @@
  */
 int32_t RuleBasedCollator::getMaxExpansion(int32_t order) const
 {
-  uint8_t result;
-  UCOL_GETMAXEXPANSION(ucollator, (uint32_t)order, result);
-  return result;
+    uint8_t result;
+    UCOL_GETMAXEXPANSION(ucollator, (uint32_t)order, result);
+    return result;
 }
 
 uint8_t* RuleBasedCollator::cloneRuleData(int32_t &length,
                                               UErrorCode &status)
 {
-  return ucol_cloneRuleData(ucollator, &length, &status);
+    return ucol_cloneRuleData(ucollator, &length, &status);
 }
 
 void RuleBasedCollator::setAttribute(UColAttribute attr,
                                      UColAttributeValue value,
                                      UErrorCode &status)
 {
-  if (U_FAILURE(status))
-    return;
-  checkOwned();
-  ucol_setAttribute(ucollator, attr, value, &status);
+    if (U_FAILURE(status))
+        return;
+    checkOwned();
+    ucol_setAttribute(ucollator, attr, value, &status);
 }
 
 UColAttributeValue RuleBasedCollator::getAttribute(UColAttribute attr,
                                                       UErrorCode &status)
 {
-  if (U_FAILURE(status))
-    return UCOL_DEFAULT;
-  return ucol_getAttribute(ucollator, attr, &status);
+    if (U_FAILURE(status))
+        return UCOL_DEFAULT;
+    return ucol_getAttribute(ucollator, attr, &status);
 }
 
 uint32_t RuleBasedCollator::setVariableTop(const UChar *varTop, int32_t len, UErrorCode &status) {
-	checkOwned();
-	return ucol_setVariableTop(ucollator, varTop, len, &status);
+    checkOwned();
+    return ucol_setVariableTop(ucollator, varTop, len, &status);
 }
 
 uint32_t RuleBasedCollator::setVariableTop(const UnicodeString varTop, UErrorCode &status) {
-	checkOwned();
-	return ucol_setVariableTop(ucollator, varTop.getBuffer(), varTop.length(), &status);
+    checkOwned();
+    return ucol_setVariableTop(ucollator, varTop.getBuffer(), varTop.length(), &status);
 }
 
 void RuleBasedCollator::setVariableTop(const uint32_t varTop, UErrorCode &status) {
-	checkOwned();
-	ucol_restoreVariableTop(ucollator, varTop, &status);
+    checkOwned();
+    ucol_restoreVariableTop(ucollator, varTop, &status);
 }
 
 uint32_t RuleBasedCollator::getVariableTop(UErrorCode &status) const {
@@ -505,20 +510,20 @@
 
 Collator* RuleBasedCollator::safeClone(void)
 {
-  UErrorCode intStatus = U_ZERO_ERROR;
-  int32_t buffersize = U_COL_SAFECLONE_BUFFERSIZE;
-  UCollator *ucol = ucol_safeClone(ucollator, NULL, &buffersize, 
-                                   &intStatus);
-  if (U_FAILURE(intStatus)) {
-    return NULL;
-  }
+    UErrorCode intStatus = U_ZERO_ERROR;
+    int32_t buffersize = U_COL_SAFECLONE_BUFFERSIZE;
+    UCollator *ucol = ucol_safeClone(ucollator, NULL, &buffersize,
+                                    &intStatus);
+    if (U_FAILURE(intStatus)) {
+        return NULL;
+    }
 
-  UnicodeString *r = new UnicodeString(*urulestring);
-  RuleBasedCollator *result = new RuleBasedCollator(ucol, r);
-  result->dataIsOwned = TRUE;
-  result->isWriteThroughAlias = FALSE;
+    UnicodeString *r = new UnicodeString(*urulestring);
+    RuleBasedCollator *result = new RuleBasedCollator(ucol, r);
+    result->dataIsOwned = TRUE;
+    result->isWriteThroughAlias = FALSE;
 
-  return result;
+    return result;
 }
 
 
@@ -526,29 +531,29 @@
                                          uint8_t *result, int32_t resultLength)
                                          const
 {
-  return ucol_getSortKey(ucollator, source.getBuffer(), source.length(), result, resultLength);
+    return ucol_getSortKey(ucollator, source.getBuffer(), source.length(), result, resultLength);
 }
 
 int32_t RuleBasedCollator::getSortKey(const UChar *source,
                                          int32_t sourceLength, uint8_t *result,
                                          int32_t resultLength) const
 {
-  return ucol_getSortKey(ucollator, source, sourceLength, result, resultLength);
+    return ucol_getSortKey(ucollator, source, sourceLength, result, resultLength);
 }
 
 Collator::ECollationStrength RuleBasedCollator::getStrength(void) const
 {
-  UErrorCode intStatus = U_ZERO_ERROR;
-  return getECollationStrength(ucol_getAttribute(ucollator, UCOL_STRENGTH,
-                               &intStatus));
+    UErrorCode intStatus = U_ZERO_ERROR;
+    return getECollationStrength(ucol_getAttribute(ucollator, UCOL_STRENGTH,
+                                &intStatus));
 }
 
 void RuleBasedCollator::setStrength(ECollationStrength newStrength)
 {
-  checkOwned();
-  UErrorCode intStatus = U_ZERO_ERROR;
-  UCollationStrength strength = getUCollationStrength(newStrength);
-  ucol_setAttribute(ucollator, UCOL_STRENGTH, strength, &intStatus);
+    checkOwned();
+    UErrorCode intStatus = U_ZERO_ERROR;
+    UCollationStrength strength = getUCollationStrength(newStrength);
+    ucol_setAttribute(ucollator, UCOL_STRENGTH, strength, &intStatus);
 }
 
 /**
@@ -557,28 +562,28 @@
 */
 int32_t RuleBasedCollator::hashCode() const
 {
-  int32_t length;
-  const UChar *rules = ucol_getRules(ucollator, &length);
-  return uhash_hashUCharsN(rules, length);
+    int32_t length;
+    const UChar *rules = ucol_getRules(ucollator, &length);
+    return uhash_hashUCharsN(rules, length);
 }
 
 /**
 * return the locale of this collator
 */
 const Locale RuleBasedCollator::getLocale(ULocDataLocaleType type, UErrorCode &status) const {
-  const char *result = ucol_getLocale(ucollator, type, &status);
-  if(result == NULL) {
-    Locale res("");
-    res.setToBogus();
-    return res;
-  } else {
-    return Locale(result);
-  }
+    const char *result = ucol_getLocale(ucollator, type, &status);
+    if(result == NULL) {
+        Locale res("");
+        res.setToBogus();
+        return res;
+    } else {
+        return Locale(result);
+    }
 }
 
 void
 RuleBasedCollator::setLocales(const Locale& requestedLocale, const Locale& validLocale) {
-	checkOwned();
+    checkOwned();
     size_t rlen = uprv_strlen(requestedLocale.getName());
     char* rloc  = (char *)uprv_malloc((rlen+1)*sizeof(char));
     if (rloc) {
@@ -596,107 +601,105 @@
 
 // RuleBaseCollatorNew private constructor ----------------------------------
 
-RuleBasedCollator::RuleBasedCollator() 
+RuleBasedCollator::RuleBasedCollator()
   : dataIsOwned(FALSE), isWriteThroughAlias(FALSE), ucollator(0), urulestring(0)
 {
 }
 
 RuleBasedCollator::RuleBasedCollator(UCollator *collator,
                                      UnicodeString *rule)
-  : dataIsOwned(FALSE), isWriteThroughAlias(FALSE), urulestring(0) 
+  : dataIsOwned(FALSE), isWriteThroughAlias(FALSE), urulestring(0)
 {
-  ucollator = collator;
-  urulestring = rule;
+    ucollator = collator;
+    urulestring = rule;
 }
 
 RuleBasedCollator::RuleBasedCollator(const Locale& desiredLocale,
                                            UErrorCode& status) :
                                      dataIsOwned(FALSE), ucollator(0), urulestring(0)
 {
-  if (U_FAILURE(status))
-    return;
+    if (U_FAILURE(status))
+        return;
 
-  /*
-  Try to load, in order:
-   1. The desired locale's collation.
-   2. A fallback of the desired locale.
-   3. The default locale's collation.
-   4. A fallback of the default locale.
-   5. The default collation rules, which contains en_US collation rules.
+    /*
+    Try to load, in order:
+     1. The desired locale's collation.
+     2. A fallback of the desired locale.
+     3. The default locale's collation.
+     4. A fallback of the default locale.
+     5. The default collation rules, which contains en_US collation rules.
 
-   To reiterate, we try:
-   Specific:
-    language+country+variant
-    language+country
-    language
-   Default:
-    language+country+variant
-    language+country
-    language
-   Root: (aka DEFAULTRULES)
-   steps 1-5 are handled by resource bundle fallback mechanism.
-   however, in a very unprobable situation that no resource bundle
-   data exists, step 5 is repeated with hardcoded default rules.
-  */
+     To reiterate, we try:
+     Specific:
+      language+country+variant
+      language+country
+      language
+     Default:
+      language+country+variant
+      language+country
+      language
+     Root: (aka DEFAULTRULES)
+     steps 1-5 are handled by resource bundle fallback mechanism.
+     however, in a very unprobable situation that no resource bundle
+     data exists, step 5 is repeated with hardcoded default rules.
+    */
 
-  setUCollator(desiredLocale, status);
+    setUCollator(desiredLocale, status);
 
-  if (U_FAILURE(status))
-  {
-    status = U_ZERO_ERROR;
+    if (U_FAILURE(status))
+    {
+        status = U_ZERO_ERROR;
 
-    setUCollator(kRootLocaleName, status);
-    if (status == U_ZERO_ERROR) {
-        status = U_USING_DEFAULT_WARNING;
+        setUCollator(kRootLocaleName, status);
+        if (status == U_ZERO_ERROR) {
+            status = U_USING_DEFAULT_WARNING;
+        }
     }
-  }
 
-  if (U_SUCCESS(status))
-  {
-    int32_t length;
-    const UChar *r = ucol_getRules(ucollator, &length);
-    if (length > 0) {
-        // alias the rules string
-        urulestring = new UnicodeString(TRUE, r, length);
-    }
-    else {
-        urulestring = new UnicodeString();
-    }
-    /* test for NULL */
-    if (urulestring == 0) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        return;
+    if (U_SUCCESS(status))
+    {
+        int32_t length;
+        const UChar *r = ucol_getRules(ucollator, &length);
+        if (length > 0) {
+            // alias the rules string
+            urulestring = new UnicodeString(TRUE, r, length);
+        }
+        else {
+            urulestring = new UnicodeString();
+        }
+        /* test for NULL */
+        if (urulestring == 0) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+            return;
+        }
+        dataIsOwned = TRUE;
+        isWriteThroughAlias = FALSE;
     }
-    dataIsOwned = TRUE;
-	isWriteThroughAlias = FALSE;
-  }
-
-  return;
 }
 
 void 
 RuleBasedCollator::setUCollator(const char *locale,
                                 UErrorCode &status)
 {
-  if (U_FAILURE(status))
-    return;
-  if (ucollator && dataIsOwned)
-    ucol_close(ucollator);
-  ucollator = ucol_open_internal(locale, &status);
-  dataIsOwned = TRUE;
-  isWriteThroughAlias = FALSE;
+    if (U_FAILURE(status))
+        return;
+    if (ucollator && dataIsOwned)
+        ucol_close(ucollator);
+    ucollator = ucol_open_internal(locale, &status);
+    dataIsOwned = TRUE;
+    isWriteThroughAlias = FALSE;
 }
 
 
 void
 RuleBasedCollator::checkOwned() {
-	if (!(dataIsOwned || isWriteThroughAlias)) {
-		UErrorCode status = U_ZERO_ERROR;
-		ucollator = ucol_safeClone(ucollator, NULL, NULL, &status);
-		setRuleStringFromCollator(status);
-		dataIsOwned = TRUE;
-		isWriteThroughAlias = FALSE;
-	}
+    if (!(dataIsOwned || isWriteThroughAlias)) {
+        UErrorCode status = U_ZERO_ERROR;
+        ucollator = ucol_safeClone(ucollator, NULL, NULL, &status);
+        setRuleStringFromCollator(status);
+        dataIsOwned = TRUE;
+        isWriteThroughAlias = FALSE;
+    }
 }
 
 /* RuleBasedCollator private data members -------------------------------- */
@@ -751,12 +754,7 @@
 
 const int32_t RuleBasedCollator::PRIMIGNORABLE = 0x0202;
 
-/* unique file id for parity check */
-const int16_t RuleBasedCollator::FILEID = 0x5443;
-/* binary collation file extension */
-const char RuleBasedCollator::kFilenameSuffix[] = ".col";
-/* class id ? Value is irrelevant */
-const char  RuleBasedCollator::fgClassID = 0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedCollator)
 
 U_NAMESPACE_END
 

Index: timezone.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/timezone.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- timezone.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ timezone.cpp	6 Apr 2004 10:08:51 -0000	1.4
@@ -36,40 +36,56 @@
 *********************************************************************************/
 
 #include "unicode/utypes.h"
+#include "unicode/ustring.h"
+
+#ifdef U_DEBUG_TZ
+# include <stdio.h>
+# include "uresimp.h" // for debugging
+
+static void debug_tz_loc(const char *f, int32_t l)
+{
[...1330 lines suppressed...]
+#ifdef U_DEBUG_TZ
+    char buf[128];
+    fID.extract(0, sizeof(buf)-1, buf, sizeof(buf), "");
+#endif
     SimpleDateFormat format(style == LONG ? "zzzz" : "z",locale,status);
-
+    U_DEBUG_TZ_MSG(("getDisplayName(%s)\n", buf));
     if(!U_SUCCESS(status))
     {
-        // *** SRL what do I do here?!!
-        return result.remove();
+#ifdef U_DEBUG_TZ
+      char buf2[128];
+      result.extract(0, sizeof(buf2)-1, buf2, sizeof(buf2), "");
+      U_DEBUG_TZ_MSG(("getDisplayName(%s) -> %s\n", buf, buf2));
+#endif
+      return result.remove();
     }
 
     // Create a new SimpleTimeZone as a stand-in for this zone; the

Index: titletrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/titletrn.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- titletrn.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ titletrn.cpp	6 Apr 2004 10:08:51 -0000	1.5
@@ -23,12 +23,12 @@
 
 U_NAMESPACE_BEGIN
 
-const char TitlecaseTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TitlecaseTransliterator)
 
 /**
  * ID for this transliterator.
  */
-const char TitlecaseTransliterator::_ID[] = "Any-Title";
+const char CURR_ID[] = "Any-Title";
 
 /**
  * The set of characters we skip.  These are neither cased nor
@@ -45,7 +45,7 @@
 static UnicodeSet* CASED = NULL;
 
 TitlecaseTransliterator::TitlecaseTransliterator(const Locale& theLoc) :
-    Transliterator(_ID, 0),
+    Transliterator(UnicodeString(CURR_ID, ""), 0),
     loc(theLoc), 
     buffer(0)
 {
@@ -120,7 +120,9 @@
  */
 void TitlecaseTransliterator::handleTransliterate(
                                   Replaceable& text, UTransPosition& offsets,
-                                  UBool isIncremental) const {
+                                  UBool /*isIncremental*/) const
+{
+    /* TODO: Verify that isIncremental can be ignored */
     if (SKIP == NULL) {
         return;
     }

Index: titletrn.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/titletrn.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- titletrn.h	10 Sep 2003 02:42:24 -0000	1.3
+++ titletrn.h	6 Apr 2004 10:08:51 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -27,12 +27,6 @@
  * @author Alan Liu
  */
 class U_I18N_API TitlecaseTransliterator : public Transliterator {
-
-    /**
-     * ID for this transliterator.
-     */
-    static const char _ID[];
-
  public:
 
     /**
@@ -67,14 +61,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -97,15 +91,9 @@
      * CALL.
      */
     static void cleanup();
- private:
+private:
     Locale loc;
     UChar* buffer;
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: tolowtrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/tolowtrn.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- tolowtrn.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ tolowtrn.cpp	6 Apr 2004 10:08:51 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -20,14 +20,15 @@
 
 U_NAMESPACE_BEGIN
 
-const char LowercaseTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LowercaseTransliterator)
 
-const char LowercaseTransliterator::_ID[] = "Any-Lower";
+const char CURR_ID[] = "Any-Lower";
 
 /**
  * Constructs a transliterator.
  */
-LowercaseTransliterator::LowercaseTransliterator(const Locale& theLoc) : Transliterator(_ID, 0),
+LowercaseTransliterator::LowercaseTransliterator(const Locale& theLoc) : 
+    Transliterator(UnicodeString(CURR_ID, ""), 0),
     loc(theLoc) , buffer(0)
 {
     buffer = (UChar *)uprv_malloc(u_getMaxCaseExpansion()*sizeof(buffer[0]));
@@ -73,8 +74,9 @@
  */
 void LowercaseTransliterator::handleTransliterate(Replaceable& text,
                                  UTransPosition& offsets, 
-                                 UBool isIncremental) const
+                                 UBool /*isIncremental*/) const
 {
+    /* TODO: Verify that isIncremental can be ignored */
     int32_t textPos = offsets.start;
     if (textPos >= offsets.limit) return;
 

Index: tolowtrn.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/tolowtrn.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- tolowtrn.h	10 Sep 2003 02:42:24 -0000	1.3
+++ tolowtrn.h	6 Apr 2004 10:08:51 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -60,14 +60,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -84,17 +84,11 @@
                                      UTransPosition& offsets, 
                                      UBool isIncremental) const;
 
- private:
+private:
 
     Locale loc;
     UChar* buffer;
-    static const char _ID[];
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: toupptrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/toupptrn.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- toupptrn.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ toupptrn.cpp	6 Apr 2004 10:08:51 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -20,15 +20,15 @@
 
 U_NAMESPACE_BEGIN
 
-const char UppercaseTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UppercaseTransliterator)
 
-const char UppercaseTransliterator::_ID[] = "Any-Upper";
+const char CURR_ID[] = "Any-Upper";
 
 /**
  * Constructs a transliterator.
  */
 UppercaseTransliterator::UppercaseTransliterator(const Locale& theLoc) :
-    Transliterator(_ID, 0),
+    Transliterator(UnicodeString(CURR_ID, ""), 0),
     loc(theLoc), 
     buffer(0)
 {
@@ -77,9 +77,12 @@
  */
 void UppercaseTransliterator::handleTransliterate(Replaceable& text,
                                  UTransPosition& offsets, 
-                                 UBool isIncremental) const {
+                                 UBool /*isIncremental*/) const
+{
+    /* TODO: Verify that isIncremental can be ignored */
     int32_t textPos = offsets.start;
-    if (textPos >= offsets.limit) return;
+    if (textPos >= offsets.limit)
+        return;
 
     // get string for context
     

Index: toupptrn.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/toupptrn.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- toupptrn.h	10 Sep 2003 02:42:24 -0000	1.3
+++ toupptrn.h	6 Apr 2004 10:08:51 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -60,14 +60,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -85,17 +85,11 @@
                                      UTransPosition& offsets, 
                                      UBool isIncremental) const;
 
- private:
+private:
 
     Locale loc;
     UChar* buffer;
-    static const char _ID[];
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: translit.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/translit.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- translit.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ translit.cpp	6 Apr 2004 10:08:51 -0000	1.6
@@ -101,12 +101,6 @@
 U_NAMESPACE_BEGIN
 
 /**
- * Class identifier for subclasses of Transliterator that do not
- * define their class (anonymous subclasses).
- */
-const char Transliterator::fgClassID = 0; // Value is irrelevant
-
-/**
  * Return TRUE if the given UTransPosition is valid for text of
  * the given length.
  */
@@ -129,7 +123,11 @@
 Transliterator::Transliterator(const UnicodeString& theID,
                                UnicodeFilter* adoptedFilter) :
     UObject(), ID(theID), filter(adoptedFilter),
-    maximumContextLength(0) {}
+    maximumContextLength(0) {
+
+    // NUL-terminate the ID string
+    ID.getTerminatedBuffer();
+}
 
 /**
  * Destructor.
@@ -144,6 +142,10 @@
 Transliterator::Transliterator(const Transliterator& other) :
     UObject(other), ID(other.ID), filter(0),
     maximumContextLength(other.maximumContextLength) {
+
+    // NUL-terminate the ID string
+    ID.getTerminatedBuffer();
+
     if (other.filter != 0) {
         // We own the filter, so we must have our own copy
         filter = (UnicodeFilter*) other.filter->clone();
@@ -155,6 +157,9 @@
  */
 Transliterator& Transliterator::operator=(const Transliterator& other) {
     ID = other.ID;
+    // NUL-terminate the ID string
+    ID.getTerminatedBuffer();
+
     maximumContextLength = other.maximumContextLength;
     adoptFilter((other.filter == 0) ? 0 : (UnicodeFilter*) other.filter->clone());
     return *this;

Index: transreg.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/transreg.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- transreg.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ transreg.cpp	6 Apr 2004 10:08:51 -0000	1.6
@@ -655,7 +655,10 @@
     if (visible) {
         registerSTV(source, target, variant);
         if (!availableIDs.contains((void*) &ID)) {
-            availableIDs.addElement(new UnicodeString(ID), status);
+            UnicodeString *newID = (UnicodeString *)ID.clone();
+            // NUL-terminate the ID string
+            newID->getTerminatedBuffer();
+            availableIDs.addElement(newID, status);
         }
     } else {
         removeSTV(source, target, variant);

Index: tridpars.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/tridpars.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- tridpars.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ tridpars.cpp	6 Apr 2004 10:08:52 -0000	1.2
@@ -251,7 +251,7 @@
     if (UnicodeSet::resemblesPattern(id, pos)) {
         ParsePosition ppos(pos);
         UErrorCode ec = U_ZERO_ERROR;
-        filter = new UnicodeSet(id, ppos, USET_IGNORE_SPACE, ec);
+        filter = new UnicodeSet(id, ppos, USET_IGNORE_SPACE, NULL, ec);
         /* test for NULL */
         if (filter == 0) {
             pos = start;
@@ -705,7 +705,7 @@
 
             ParsePosition ppos(pos);
             UErrorCode ec = U_ZERO_ERROR;
-            UnicodeSet set(id, ppos, USET_IGNORE_SPACE, ec);
+            UnicodeSet set(id, ppos, USET_IGNORE_SPACE, NULL, ec);
             if (U_FAILURE(ec)) {
                 pos = start;
                 return NULL;

Index: ucal.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucal.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ucal.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ ucal.cpp	6 Apr 2004 10:08:52 -0000	1.5
@@ -76,14 +76,32 @@
 ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) {
     int32_t result = 0;
     TimeZone* zone = _createTimeZone(zoneID, -1, ec);
-    if (U_SUCCESS(*ec) &&
-        zone->getDynamicClassID() == SimpleTimeZone::getStaticClassID()) {
-        result = ((SimpleTimeZone*) zone)->getDSTSavings();
+    if (U_SUCCESS(*ec)) {
+        if (zone->getDynamicClassID() == SimpleTimeZone::getStaticClassID()) {
+            result = ((SimpleTimeZone*) zone)->getDSTSavings();
+        } else {
+            // Since there is no getDSTSavings on TimeZone, we use a
+            // heuristic: Starting with the current time, march
+            // forwards for one year, looking for DST savings.
+            // Stepping by weeks is sufficient.
+            UDate d = Calendar::getNow();
+            for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) {
+                int32_t raw, dst;
+                zone->getOffset(d, FALSE, raw, dst, *ec);
+                if (U_FAILURE(*ec)) {
+                    break;
+                } else if (dst != 0) {
+                    result = dst;
+                    break;
+                }
+            }
+        }
     }
     delete zone;
     return result;
 }
 
+#ifdef U_USE_UCAL_OBSOLETE_2_8
 U_CAPI const UChar* U_EXPORT2
 ucal_getAvailableTZIDs(        int32_t         rawOffset,
                 int32_t         index,
@@ -129,6 +147,7 @@
   uprv_free(tzs);
   return count;
 }
+#endif
 
 U_CAPI UDate  U_EXPORT2
 ucal_getNow()
@@ -449,6 +468,18 @@
     break;
   }
   return -1;
+}
+
+U_CAPI const char * U_EXPORT2
+ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status) 
+{
+    if (cal == NULL) {
+        if (U_SUCCESS(*status)) {
+            *status = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        return NULL;
+    }
+    return ((Calendar*)cal)->getLocaleID(type, *status);
 }
 
 #endif /* #if !UCONFIG_NO_FORMATTING */

Index: ucol.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol.cpp	6 Apr 2004 10:08:52 -0000	1.6
@@ -41,8 +41,9 @@
 #include "uresimp.h"
 #include "umutex.h"
 #include "uhash.h"
-#include "ucln_in.h" 
+#include "ucln_in.h"
 #include "cstring.h"
+#include "utracimp.h"
 
 #ifdef UCOL_DEBUG
 #include <stdio.h>
@@ -60,10 +61,18 @@
[...3221 lines suppressed...]
-  ucol_tok_initTokenList(&targetParser, targetRules, targetRulesLen, UCA, &status);
+  ucol_tok_initTokenList(&sourceParser, sourceRules, sourceRulesLen, source->UCA, &status);
+  ucol_tok_initTokenList(&targetParser, targetRules, targetRulesLen, target->UCA, &status);
   sourceListLen = ucol_tok_assembleTokenList(&sourceParser, &parseError, &status);
   targetListLen = ucol_tok_assembleTokenList(&targetParser, &parseError, &status);
 
@@ -8252,4 +9164,13 @@
   return result;
 
 }
+
+U_CAPI void U_EXPORT2
+ucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
+  if(coll) {
+    uprv_memcpy(info, coll->UCA->image->UCAVersion, sizeof(UVersionInfo));
+  }
+}
+
 #endif /* #if !UCONFIG_NO_COLLATION */
+

Index: ucol_bld.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_bld.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_bld.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_bld.cpp	6 Apr 2004 10:08:52 -0000	1.6
@@ -28,7 +28,7 @@
 #include "umutex.h"
 #include "unicode/uniset.h"
 
-static const InverseUCATableHeader* invUCA = NULL;
+static const InverseUCATableHeader* _staticInvUCA = NULL;
 static UDataMemory* invUCA_DATA_MEM = NULL;
 
 U_CDECL_BEGIN
@@ -68,11 +68,11 @@
 U_CDECL_END
 
 static
-int32_t ucol_inv_findCE(uint32_t CE, uint32_t SecondCE) {
-  uint32_t bottom = 0, top = invUCA->tableSize;
+int32_t ucol_inv_findCE(const UColTokenParser *src, uint32_t CE, uint32_t SecondCE) {
+  uint32_t bottom = 0, top = src->invUCA->tableSize;
   uint32_t i = 0;
   uint32_t first = 0, second = 0;
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
 
   while(bottom < top-1) {
     i = (top+bottom)/2;
@@ -116,13 +116,14 @@
   0xFFFFFFFF
 };
 
-U_CAPI int32_t U_EXPORT2 ucol_inv_getNextCE(uint32_t CE, uint32_t contCE, 
+U_CAPI int32_t U_EXPORT2 ucol_inv_getNextCE(const UColTokenParser *src,
+                                            uint32_t CE, uint32_t contCE, 
                                             uint32_t *nextCE, uint32_t *nextContCE, 
                                             uint32_t strength) {
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
   int32_t iCE;
 
-  iCE = ucol_inv_findCE(CE, contCE);
+  iCE = ucol_inv_findCE(src, CE, contCE);
 
   if(iCE<0) {
     *nextCE = UCOL_NOT_FOUND;
@@ -144,13 +145,14 @@
   return iCE;
 }
 
-U_CAPI int32_t U_EXPORT2 ucol_inv_getPrevCE(uint32_t CE, uint32_t contCE, 
+U_CAPI int32_t U_EXPORT2 ucol_inv_getPrevCE(const UColTokenParser *src, 
+                                            uint32_t CE, uint32_t contCE, 
                                             uint32_t *prevCE, uint32_t *prevContCE, 
                                             uint32_t strength) {
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
   int32_t iCE;
 
-  iCE = ucol_inv_findCE(CE, contCE);
+  iCE = ucol_inv_findCE(src, CE, contCE);
 
   if(iCE<0) {
     *prevCE = UCOL_NOT_FOUND;
@@ -175,16 +177,16 @@
 }
 
 static
-inline int32_t ucol_inv_getPrevious(UColTokListHeader *lh, uint32_t strength) {
+inline int32_t ucol_inv_getPrevious(UColTokenParser *src, UColTokListHeader *lh, uint32_t strength) {
 
   uint32_t CE = lh->baseCE;
   uint32_t SecondCE = lh->baseContCE; 
 
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
   uint32_t previousCE, previousContCE;
   int32_t iCE;
 
-  iCE = ucol_inv_findCE(CE, SecondCE);
+  iCE = ucol_inv_findCE(src, CE, SecondCE);
 
   if(iCE<0) {
     return -1;
@@ -207,15 +209,15 @@
 }
 
 static
-inline int32_t ucol_inv_getNext(UColTokListHeader *lh, uint32_t strength) {
+inline int32_t ucol_inv_getNext(UColTokenParser *src, UColTokListHeader *lh, uint32_t strength) {
   uint32_t CE = lh->baseCE;
   uint32_t SecondCE = lh->baseContCE; 
 
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
   uint32_t nextCE, nextContCE;
   int32_t iCE;
 
-  iCE = ucol_inv_findCE(CE, SecondCE);
+  iCE = ucol_inv_findCE(src, CE, SecondCE);
 
   if(iCE<0) {
     return -1;
@@ -242,7 +244,7 @@
 U_CFUNC void ucol_inv_getGapPositions(UColTokenParser *src, UColTokListHeader *lh, UErrorCode *status) {
   /* reset all the gaps */
   int32_t i = 0;
-  uint32_t *CETable = (uint32_t *)((uint8_t *)invUCA+invUCA->table);
+  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
   uint32_t st = 0;
   uint32_t t1, t2;
   int32_t pos;
@@ -265,7 +267,7 @@
 
   UCAConstants *consts = (UCAConstants *)((uint8_t *)src->UCA->image + src->UCA->image->UCAConsts);
 
-  if(lh->baseCE >= (consts->UCA_PRIMARY_IMPLICIT_MIN<<24) && lh->baseCE < (consts->UCA_PRIMARY_IMPLICIT_MAX<<24) ) { /* implicits - */ 
+  if((lh->baseCE & 0xFF000000)>= (consts->UCA_PRIMARY_IMPLICIT_MIN<<24) && (lh->baseCE & 0xFF000000) <= (consts->UCA_PRIMARY_IMPLICIT_MAX<<24) ) { /* implicits - */ 
   //if(lh->baseCE >= PRIMARY_IMPLICIT_MIN && lh->baseCE < PRIMARY_IMPLICIT_MAX ) { /* implicits - */ 
     lh->pos[0] = 0;
     t1 = lh->baseCE;
@@ -273,16 +275,12 @@
     lh->gapsLo[0] = (t1 & UCOL_PRIMARYMASK) | (t2 & UCOL_PRIMARYMASK) >> 16;
     lh->gapsLo[1] = (t1 & UCOL_SECONDARYMASK) << 16 | (t2 & UCOL_SECONDARYMASK) << 8;
     lh->gapsLo[2] = (UCOL_TERTIARYORDER(t1)) << 24 | (UCOL_TERTIARYORDER(t2)) << 16;
-    if(lh->baseCE < 0xEF000000) {
-    /* first implicits have three byte primaries, with a gap of one */
-    /* so we esentially need to add 2 to the top byte in lh->baseContCE */
-      t2 += 0x02000000;
-    } else {
-    /* second implicits have four byte primaries, with a gap of IMPLICIT_LAST2_MULTIPLIER_ */
-    /* Now, this guy is not really accessible here, so until we find a better way to pass it */
-    /* around, we'll assume that the gap is 1 */
-      t2 += 0x00020000;
-    }
+    uint32_t primaryCE = t1 & UCOL_PRIMARYMASK | (t2 & UCOL_PRIMARYMASK) >> 16;
+    primaryCE = uprv_uca_getImplicitFromRaw(uprv_uca_getRawFromImplicit(primaryCE)+1);
+
+    t1 = primaryCE & UCOL_PRIMARYMASK | 0x0505;
+    t2 = (primaryCE << 16) & UCOL_PRIMARYMASK | UCOL_CONTINUATION_MARKER;
+
     lh->gapsHi[0] = (t1 & UCOL_PRIMARYMASK) | (t2 & UCOL_PRIMARYMASK) >> 16;
     lh->gapsHi[1] = (t1 & UCOL_SECONDARYMASK) << 16 | (t2 & UCOL_SECONDARYMASK) << 8;
     lh->gapsHi[2] = (UCOL_TERTIARYORDER(t1)) << 24 | (UCOL_TERTIARYORDER(t2)) << 16;
@@ -302,7 +300,7 @@
   } else {
     for(;;) {
       if(tokStrength < UCOL_CE_STRENGTH_LIMIT) {
-        if((lh->pos[tokStrength] = ucol_inv_getNext(lh, tokStrength)) >= 0) {
+        if((lh->pos[tokStrength] = ucol_inv_getNext(src, lh, tokStrength)) >= 0) {
           lh->fStrToken[tokStrength] = tok;
         } else { /* The CE must be implicit, since it's not in the table */
           /* Error */
@@ -402,7 +400,14 @@
   uint32_t strength = tok->strength;
   uint32_t low = lows[fStrength*3+strength];
   uint32_t high = highs[fStrength*3+strength];
-  uint32_t maxByte = (strength == UCOL_TERTIARY)?0x3F:0xFF;
+  uint32_t maxByte = 0;
+  if(strength == UCOL_TERTIARY) {
+      maxByte = 0x3F;
+  } else if(strength == UCOL_PRIMARY) {
+      maxByte = 0xFE;
+  } else {
+      maxByte = 0xFF;
+  }
 
   uint32_t count = tok->toInsert;
 
@@ -440,8 +445,8 @@
       high = UCOL_COMMON_TOP2<<24;
     } 
     if(low < UCOL_COMMON_BOT2<<24) {
-      g->noOfRanges = ucol_allocWeights(UCOL_COMMON_TOP2<<24, high, count, maxByte, g->ranges);
-      g->current = UCOL_COMMON_BOT2;
+      g->noOfRanges = ucol_allocWeights(UCOL_COMMON_BOT2<<24, high, count, maxByte, g->ranges);
+      g->current = UCOL_COMMON_BOT2<<24;
       return g->current;
     }
   } 
@@ -454,7 +459,127 @@
   return g->current;
 }
 
-U_CFUNC void ucol_doCE(uint32_t *CEparts, UColToken *tok) {
+static
+uint32_t u_toLargeKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
+  uint32_t i = 0; 
+  UChar c;
+
+  if(U_FAILURE(*status)) {
+    return 0;
+  }
+
+  if(sourceLen > resLen) {
+    *status = U_MEMORY_ALLOCATION_ERROR;
+    return 0;
+  }
+  
+  for(i = 0; i < sourceLen; i++) {
+    c = source[i];
+    if(0x3042 < c && c < 0x30ef) { /* Kana range */
+      switch(c - 0x3000) {
+      case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x63: case 0x83: case 0x85: case 0x8E:
+      case 0xA1: case 0xA3: case 0xA5: case 0xA7: case 0xA9: case 0xC3: case 0xE3: case 0xE5: case 0xEE:
+        c++;
+        break;
+      case 0xF5:
+        c = 0x30AB;
+        break;
+      case 0xF6:
+        c = 0x30B1;
+        break;
+      }
+    }
+    resBuf[i] = c;
+  }
+  return sourceLen;
+}
+
+static
+uint32_t u_toSmallKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
+  uint32_t i = 0; 
+  UChar c;
+
+  if(U_FAILURE(*status)) {
+    return 0;
+  }
+
+  if(sourceLen > resLen) {
+    *status = U_MEMORY_ALLOCATION_ERROR;
+    return 0;
+  }
+  
+  for(i = 0; i < sourceLen; i++) {
+    c = source[i];
+    if(0x3042 < c && c < 0x30ef) { /* Kana range */
+      switch(c - 0x3000) {
+      case 0x42: case 0x44: case 0x46: case 0x48: case 0x4A: case 0x64: case 0x84: case 0x86: case 0x8F:
+      case 0xA2: case 0xA4: case 0xA6: case 0xA8: case 0xAA: case 0xC4: case 0xE4: case 0xE6: case 0xEF:
+        c--;
+        break;
+      case 0xAB:
+        c = 0x30F5;
+        break;
+      case 0xB1:
+        c = 0x30F6;
+        break;
+      }
+    }
+    resBuf[i] = c;
+  }
+  return sourceLen;
+}
+
+static
+uint8_t ucol_uprv_getCaseBits(const UCollator *UCA, const UChar *src, uint32_t len, UErrorCode *status) {
+  uint32_t i = 0;
+  UChar n[128];
+  uint32_t nLen = 0;
+  uint32_t uCount = 0, lCount = 0;
+
+  collIterate s;
+  uint32_t order = 0;
+
+  if(U_FAILURE(*status)) {
+    return UCOL_LOWER_CASE;
+  }
+
+  nLen = unorm_normalize(src, len, UNORM_NFKD, 0, n, 128, status);
+  if(U_SUCCESS(*status)) {
+    for(i = 0; i < nLen; i++) {
+      uprv_init_collIterate(UCA, &n[i], 1, &s);
+      order = ucol_getNextCE(UCA, &s, status);
+      if(isContinuation(order)) {
+        *status = U_INTERNAL_PROGRAM_ERROR;
+        return UCOL_LOWER_CASE;
+      }
+      if((order&UCOL_CASE_BIT_MASK)== UCOL_UPPER_CASE) {
+        uCount++;
+      } else {
+        if(u_islower(n[i])) {
+          lCount++;
+        } else {
+          UChar sk[1], lk[1];
+          u_toSmallKana(&n[i], 1, sk, 1, status);
+          u_toLargeKana(&n[i], 1, lk, 1, status);
+          if(sk[0] == n[i] && lk[0] != n[i]) {
+            lCount++;
+          }
+        }
+      }
+    }
+  }
+
+  if(uCount != 0 && lCount != 0) {
+    return UCOL_MIXED_CASE;
+  } else if(uCount != 0) {
+    return UCOL_UPPER_CASE;
+  } else {
+    return UCOL_LOWER_CASE;
+  }
+}
+
+
+U_CFUNC void ucol_doCE(UColTokenParser *src, uint32_t *CEparts, UColToken *tok, UErrorCode *status) {
   /* this one makes the table and stuff */
   uint32_t noOfBytes[3];
   uint32_t i;
@@ -494,6 +619,22 @@
     tok->noOfCEs = CEi;
   }
 
+
+  // we want to set case bits here and now, not later.
+  // Case bits handling 
+  tok->CEs[0] &= 0xFFFFFF3F; // Clean the case bits field
+  int32_t cSize = (tok->source & 0xFF000000) >> 24;
+  UChar *cPoints = (tok->source & 0x00FFFFFF) + src->source;
+
+  if(cSize > 1) {
+    // Do it manually
+    tok->CEs[0] |= ucol_uprv_getCaseBits(src->UCA, cPoints, cSize, status);
+  } else {
+    // Copy it from the UCA
+    uint32_t caseCE = ucol_getFirstCE(src->UCA, cPoints[0], status);
+    tok->CEs[0] |= (caseCE & 0xC0);
+  }
+
 #if UCOL_DEBUG==2
   fprintf(stderr, "%04X str: %i, [%08X, %08X, %08X]: tok: ", tok->debugSource, tok->strength, CEparts[0] >> (32-8*noOfBytes[0]), CEparts[1] >> (32-8*noOfBytes[1]), CEparts[2]>> (32-8*noOfBytes[2]));
   for(i = 0; i<tok->noOfCEs; i++) {
@@ -604,130 +745,11 @@
         CEparts[UCOL_TERTIARY] = ucol_getSimpleCEGenerator(&Gens[UCOL_TERTIARY], tok, UCOL_TERTIARY, status);
       }
     }
-    ucol_doCE(CEparts, tok);
+    ucol_doCE(src, CEparts, tok, status);
     tok = tok->next;
   }
 }
 
-static
-uint32_t u_toLargeKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
-  uint32_t i = 0; 
-  UChar c;
-
-  if(U_FAILURE(*status)) {
-    return 0;
-  }
-
-  if(sourceLen > resLen) {
-    *status = U_MEMORY_ALLOCATION_ERROR;
-    return 0;
-  }
-  
-  for(i = 0; i < sourceLen; i++) {
-    c = source[i];
-    if(0x3042 < c && c < 0x30ef) { /* Kana range */
-      switch(c - 0x3000) {
-      case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x63: case 0x83: case 0x85: case 0x8E:
-      case 0xA1: case 0xA3: case 0xA5: case 0xA7: case 0xA9: case 0xC3: case 0xE3: case 0xE5: case 0xEE:
-        c++;
-        break;
-      case 0xF5:
-        c = 0x30AB;
-        break;
-      case 0xF6:
-        c = 0x30B1;
-        break;
-      }
-    }
-    resBuf[i] = c;
-  }
-  return sourceLen;
-}
-
-static
-uint32_t u_toSmallKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
-  uint32_t i = 0; 
-  UChar c;
-
-  if(U_FAILURE(*status)) {
-    return 0;
-  }
-
-  if(sourceLen > resLen) {
-    *status = U_MEMORY_ALLOCATION_ERROR;
-    return 0;
-  }
-  
-  for(i = 0; i < sourceLen; i++) {
-    c = source[i];
-    if(0x3042 < c && c < 0x30ef) { /* Kana range */
-      switch(c - 0x3000) {
-      case 0x42: case 0x44: case 0x46: case 0x48: case 0x4A: case 0x64: case 0x84: case 0x86: case 0x8F:
-      case 0xA2: case 0xA4: case 0xA6: case 0xA8: case 0xAA: case 0xC4: case 0xE4: case 0xE6: case 0xEF:
-        c--;
-        break;
-      case 0xAB:
-        c = 0x30F5;
-        break;
-      case 0xB1:
-        c = 0x30F6;
-        break;
-      }
-    }
-    resBuf[i] = c;
-  }
-  return sourceLen;
-}
-
-static
-uint8_t ucol_uprv_getCaseBits(const UCollator *UCA, const UChar *src, uint32_t len, UErrorCode *status) {
-  uint32_t i = 0;
-  UChar n[128];
-  uint32_t nLen = 0;
-  uint32_t uCount = 0, lCount = 0;
-
-  collIterate s;
-  uint32_t order = 0;
-
-  if(U_FAILURE(*status)) {
-    return UCOL_LOWER_CASE;
-  }
-
-  nLen = unorm_normalize(src, len, UNORM_NFKD, 0, n, 128, status);
-  if(U_SUCCESS(*status)) {
-    for(i = 0; i < nLen; i++) {
-      uprv_init_collIterate(UCA, &n[i], 1, &s);
-      order = ucol_getNextCE(UCA, &s, status);
-      if(isContinuation(order)) {
-        *status = U_INTERNAL_PROGRAM_ERROR;
-        return UCOL_LOWER_CASE;
-      }
-      if((order&UCOL_CASE_BIT_MASK)== UCOL_UPPER_CASE) {
-        uCount++;
-      } else {
-        if(u_islower(n[i])) {
-          lCount++;
-        } else {
-          UChar sk[1], lk[1];
-          u_toSmallKana(&n[i], 1, sk, 1, status);
-          u_toLargeKana(&n[i], 1, lk, 1, status);
-          if(sk[0] == n[i] && lk[0] != n[i]) {
-            lCount++;
-          }
-        }
-      }
-    }
-  }
-
-  if(uCount != 0 && lCount != 0) {
-    return UCOL_MIXED_CASE;
-  } else if(uCount != 0) {
-    return UCOL_UPPER_CASE;
-  } else {
-    return UCOL_LOWER_CASE;
-  }
-}
-
 U_CFUNC void ucol_createElements(UColTokenParser *src, tempUCATable *t, UColTokListHeader *lh, UErrorCode *status) {
   UCAElements el;
   UColToken *tok = lh->first;
@@ -834,6 +856,8 @@
       }
     }
 
+#if 0
+    // we do case bits in doCE now, since we will mess up expansions otherwise.
     // Case bits handling 
     el.CEs[0] &= 0xFFFFFF3F; // Clean the case bits field
     if(el.cSize > 1) {
@@ -844,6 +868,7 @@
       uint32_t caseCE = ucol_getFirstCE(src->UCA, el.cPoints[0], status);
       el.CEs[0] |= (caseCE & 0xC0);
     }
+#endif
 
     /* and then, add it */
 #if UCOL_DEBUG==2
@@ -1036,7 +1061,12 @@
     /* We stuff the initial value in the buffers, and increase the appropriate buffer */
     /* According to strength                                                          */
     if(U_SUCCESS(*status)) {
-      ucol_initBuffers(src, &src->lh[i], status);
+      if(src->lh[i].first) { // if there are any elements
+        // due to the way parser works, subsequent tailorings
+        // may remove all the elements from a sequence, therefore
+        // leaving an empty tailoring sequence.
+        ucol_initBuffers(src, &src->lh[i], status);
+      }
     }
     if(U_FAILURE(*status)) {
       return NULL;
@@ -1062,7 +1092,7 @@
   }
 
 
-  tempUCATable *t = uprv_uca_initTempTable(image, src->opts, src->UCA, NOT_FOUND_TAG, status);
+  tempUCATable *t = uprv_uca_initTempTable(image, src->opts, src->UCA, NOT_FOUND_TAG, NOT_FOUND_TAG, status);
 
 
   /* After this, we have assigned CE values to all regular CEs      */
@@ -1129,7 +1159,7 @@
             el.cSize = 2;
           }
           ucol_setText(ucaEl, el.uchars, el.cSize, status);
-          while ((el.CEs[el.noOfCEs] = ucol_next(ucaEl, status)) != UCOL_NULLORDER) {
+          while ((int32_t)(el.CEs[el.noOfCEs] = ucol_next(ucaEl, status)) != UCOL_NULLORDER) {
             el.noOfCEs++;
           }
           uprv_uca_addAnElement(t, &el, status);
@@ -1166,7 +1196,7 @@
 {
     udata_close(invUCA_DATA_MEM);
     invUCA_DATA_MEM = NULL;
-    invUCA = NULL;
+    _staticInvUCA = NULL;
     return TRUE;
 }
 
@@ -1176,7 +1206,7 @@
     if(U_FAILURE(*status)) return NULL;
 
     umtx_lock(NULL);
-    UBool f = (invUCA == NULL);
+    UBool f = (_staticInvUCA == NULL);
     umtx_unlock(NULL);
     
     if(f) {
@@ -1203,8 +1233,8 @@
             }
             
             umtx_lock(NULL);
-            if(invUCA == NULL) {
-                invUCA = newInvUCA;
+            if(_staticInvUCA == NULL) {
+                _staticInvUCA = newInvUCA;
                 invUCA_DATA_MEM = result;
                 result = NULL;
                 newInvUCA = NULL;
@@ -1222,7 +1252,7 @@
             }
         }
     }
-    return invUCA;
+    return _staticInvUCA;
 }
 
 #endif /* #if !UCONFIG_NO_COLLATION */

Index: ucol_cnt.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_cnt.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_cnt.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_cnt.cpp	6 Apr 2004 10:08:53 -0000	1.6
@@ -28,7 +28,7 @@
 
 U_NAMESPACE_BEGIN
 
-void uprv_growTable(ContractionTable *tbl, UErrorCode *status) {
+static void uprv_growTable(ContractionTable *tbl, UErrorCode *status) {
     if(tbl->position == tbl->size) {
         uint32_t *newData = (uint32_t *)uprv_realloc(tbl->CEs, 2*tbl->size*sizeof(uint32_t));
         if(newData == NULL) {
@@ -228,7 +228,7 @@
     return table->position;
 }
 
-ContractionTable *uprv_cnttab_cloneContraction(ContractionTable *t, UErrorCode *status) {
+static ContractionTable *uprv_cnttab_cloneContraction(ContractionTable *t, UErrorCode *status) {
   ContractionTable *r = (ContractionTable *)uprv_malloc(sizeof(ContractionTable));
   if(r == NULL) {
     *status = U_MEMORY_ALLOCATION_ERROR;

Index: ucol_elm.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_elm.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_elm.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_elm.cpp	6 Apr 2004 10:08:53 -0000	1.6
@@ -108,7 +108,7 @@
 }
 
 U_CAPI tempUCATable*  U_EXPORT2
-uprv_uca_initTempTable(UCATableHeader *image, UColOptionSet *opts, const UCollator *UCA, UColCETags initTag, UErrorCode *status) {
+uprv_uca_initTempTable(UCATableHeader *image, UColOptionSet *opts, const UCollator *UCA, UColCETags initTag, UColCETags supplementaryInitTag, UErrorCode *status) {
   tempUCATable *t = (tempUCATable *)uprv_malloc(sizeof(tempUCATable));
   /* test for NULL */
   if (t == NULL) {
@@ -147,7 +147,12 @@
   }
   uprv_memset(t->expansions, 0, sizeof(ExpansionTable));
   /*t->mapping = ucmpe32_open(UCOL_SPECIAL_FLAG | (initTag<<24), UCOL_SPECIAL_FLAG | (SURROGATE_TAG<<24), UCOL_SPECIAL_FLAG | (LEAD_SURROGATE_TAG<<24), status);*/
-  t->mapping = utrie_open(NULL, NULL, 0x100000, UCOL_SPECIAL_FLAG | (initTag<<24), TRUE); // Do your own mallocs for the structure, array and have linear Latin 1
+  /*t->mapping = utrie_open(NULL, NULL, 0x100000, UCOL_SPECIAL_FLAG | (initTag<<24), TRUE); // Do your own mallocs for the structure, array and have linear Latin 1*/
+
+  t->mapping = utrie_open(NULL, NULL, 0x100000,
+                          UCOL_SPECIAL_FLAG | (initTag<<24),
+                          UCOL_SPECIAL_FLAG | (supplementaryInitTag << 24),
+                          TRUE); // Do your own mallocs for the structure, array and have linear Latin 1
   t->prefixLookup = uhash_open(prefixLookupHash, prefixLookupComp, status);
   uhash_setValueDeleter(t->prefixLookup, uhash_freeBlock);
 
@@ -281,7 +286,7 @@
           *status = U_MEMORY_ALLOCATION_ERROR;
           return NULL;
       }
-      uprv_memcpy(r->maxExpansions->endExpansionCE, t->maxExpansions->endExpansionCE, t->maxExpansions->size*sizeof(uint32_t));
+      uprv_memcpy(r->maxExpansions->endExpansionCE, t->maxExpansions->endExpansionCE, t->maxExpansions->position*sizeof(uint32_t));
     } else {
       r->maxExpansions->endExpansionCE = NULL;
     }
@@ -292,7 +297,7 @@
           *status = U_MEMORY_ALLOCATION_ERROR;
           return NULL;
       }
-      uprv_memcpy(r->maxExpansions->expansionCESize, t->maxExpansions->expansionCESize, t->maxExpansions->size*sizeof(uint8_t));
+      uprv_memcpy(r->maxExpansions->expansionCESize, t->maxExpansions->expansionCESize, t->maxExpansions->position*sizeof(uint8_t));
     } else {
       r->maxExpansions->expansionCESize = NULL;
     }
@@ -317,14 +322,14 @@
           *status = U_MEMORY_ALLOCATION_ERROR;
           return NULL;
       }
-      uprv_memcpy(r->maxJamoExpansions->endExpansionCE, t->maxJamoExpansions->endExpansionCE, t->maxJamoExpansions->size*sizeof(uint32_t));
+      uprv_memcpy(r->maxJamoExpansions->endExpansionCE, t->maxJamoExpansions->endExpansionCE, t->maxJamoExpansions->position*sizeof(uint32_t));
       r->maxJamoExpansions->isV = (UBool *)uprv_malloc(sizeof(UBool)*t->maxJamoExpansions->size);
       /* test for NULL */
       if (r->maxJamoExpansions->isV == NULL) {
           *status = U_MEMORY_ALLOCATION_ERROR;
           return NULL;
       }
-      uprv_memcpy(r->maxJamoExpansions->isV, t->maxJamoExpansions->isV, t->maxJamoExpansions->size*sizeof(UBool));
+      uprv_memcpy(r->maxJamoExpansions->isV, t->maxJamoExpansions->isV, t->maxJamoExpansions->position*sizeof(UBool));
     } else {
       r->maxJamoExpansions->endExpansionCE = NULL;
       r->maxJamoExpansions->isV = NULL;
@@ -401,7 +406,7 @@
 * @param status error status
 * @returns size of the maxexpansion and maxsize used.
 */
-int uprv_uca_setMaxExpansion(uint32_t           endexpansion,
+static int uprv_uca_setMaxExpansion(uint32_t           endexpansion,
                              uint8_t            expansionsize,
                              MaxExpansionTable *maxexpansion,
                              UErrorCode        *status)
@@ -465,7 +470,7 @@
       start = mid;                                                           
     }                                                                        
   } 
-      
+
   if (*start == endexpansion) {                                                     
     result = start - pendexpansionce;  
   }                                                                          
@@ -473,7 +478,7 @@
     if (*limit == endexpansion) {                                                     
       result = limit - pendexpansionce;      
     }                                            
-      
+
   if (result > -1) {
     /* found the ce in expansion, we'll just modify the size if it is 
        smaller */
@@ -489,7 +494,7 @@
     int      shiftsize     = (pendexpansionce + pos) - start;
     uint32_t *shiftpos     = start + 1;
     uint8_t  *sizeshiftpos = pexpansionsize + (shiftpos - pendexpansionce);
-    
+
     /* okay need to rearrange the array into sorted order */
     if (shiftsize == 0 || *(pendexpansionce + pos) < endexpansion) {
       *(pendexpansionce + pos + 1) = endexpansion;
@@ -543,7 +548,7 @@
 * @param status error status
 * @returns size of the maxexpansion and maxsize used.
 */
-int uprv_uca_setMaxJamoExpansion(UChar                  ch,
+static int uprv_uca_setMaxJamoExpansion(UChar                  ch,
                                  uint32_t               endexpansion,
                                  uint8_t                expansionsize,
                                  MaxJamoExpansionTable *maxexpansion,
@@ -626,7 +631,7 @@
   *(pendexpansionce + maxexpansion->position) = endexpansion;
   *(maxexpansion->isV + maxexpansion->position) = isV;
   maxexpansion->position ++;
-  
+
   return maxexpansion->position;
 }
 
@@ -700,7 +705,7 @@
     }
 }
 
-uint32_t uprv_uca_addPrefix(tempUCATable *t, uint32_t CE, 
+static uint32_t uprv_uca_addPrefix(tempUCATable *t, uint32_t CE, 
                                  UCAElements *element, UErrorCode *status) {
   // currently the longest prefix we're supporting in Japanese is two characters
   // long. Although this table could quite easily mimic complete contraction stuff
@@ -820,7 +825,7 @@
 // in the contraction, it is going to be handled as a pair of code units,
 // as it doesn't affect the performance AND handling surrogates specially
 // would complicate code way too much.
-uint32_t uprv_uca_addContraction(tempUCATable *t, uint32_t CE, 
+static uint32_t uprv_uca_addContraction(tempUCATable *t, uint32_t CE, 
                                  UCAElements *element, UErrorCode *status) {
     CntTable *contractions = t->contractions;
     UChar32 cp;
@@ -1007,9 +1012,12 @@
   if(U_FAILURE(*status)) {
       return 0xFFFF;
   }
+
+  element->mapCE = 0; // clear mapCE so that we can catch expansions
+
   if(element->noOfCEs == 1) {
     if(element->isThai == FALSE) {
-      element->mapCE = element->CEs[0];
+		  element->mapCE = element->CEs[0];      
     } else { /* add thai - totally bad here */
       expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (THAI_TAG<<UCOL_TAG_SHIFT) 
         | ((uprv_uca_addExpansion(expansions, element->CEs[0], status)+(headersize>>2))<<4) 
@@ -1043,10 +1051,10 @@
         | ((element->CEs[0]>>8) & 0xFFFF00) // first and second byte of primary
         | ((element->CEs[1]>>24) & 0xFF);   // third byte of primary
     } else {
-      expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (EXPANSION_TAG<<UCOL_TAG_SHIFT) 
-        | ((uprv_uca_addExpansion(expansions, element->CEs[0], status)+(headersize>>2))<<4)
-        & 0xFFFFF0);
-
+	  expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (EXPANSION_TAG<<UCOL_TAG_SHIFT) 
+		| ((uprv_uca_addExpansion(expansions, element->CEs[0], status)+(headersize>>2))<<4)
+		& 0xFFFFF0);
+		
       for(i = 1; i<element->noOfCEs; i++) {
         uprv_uca_addExpansion(expansions, element->CEs[i], status);
       }
@@ -1071,6 +1079,32 @@
     }
   }
 
+  // We treat digits differently - they are "uber special" and should be
+  // processed differently if numeric collation is on. 
+  UChar32 uniChar = 0;
+  //printElement(element);
+  if ((element->cSize == 2) && U16_IS_LEAD(element->uchars[0])){
+	  uniChar = U16_GET_SUPPLEMENTARY(element->uchars[0], element->uchars[1]);	  
+  } else if (element->cSize == 1){
+	  uniChar = element->uchars[0];
+  }
+
+  // Here, we either have one normal CE OR mapCE is set. Therefore, we stuff only
+  // one element to the expansion buffer. When we encounter a digit and we don't 
+  // do numeric collation, we will just pick the CE we have and break out of case
+  // (see ucol.cpp ucol_prv_getSpecialCE && ucol_prv_getSpecialPrevCE). If we picked
+  // a special, further processing will occur. If it's a simple CE, we'll return due
+  // to how the loop is constructed.
+  if (uniChar != 0 && u_isdigit(uniChar)){
+	  expansion = (uint32_t)(UCOL_SPECIAL_FLAG | (DIGIT_TAG<<UCOL_TAG_SHIFT) | 1); // prepare the element
+      if(element->mapCE) { // if there is an expansion, we'll pick it here
+        expansion |= ((uprv_uca_addExpansion(expansions, element->mapCE, status)+(headersize>>2))<<4);
+      } else {
+	    expansion |= ((uprv_uca_addExpansion(expansions, element->CEs[0], status)+(headersize>>2))<<4);
+      }
+	  element->mapCE = expansion;
+  }
+
   // here we want to add the prefix structure.
   // I will try to process it as a reverse contraction, if possible.
   // prefix buffer is already reversed.
@@ -1142,7 +1176,7 @@
 
 
 /*void uprv_uca_getMaxExpansionJamo(CompactEIntArray       *mapping, */
-void uprv_uca_getMaxExpansionJamo(UNewTrie       *mapping, 
+static void uprv_uca_getMaxExpansionJamo(UNewTrie       *mapping, 
                                   MaxExpansionTable     *maxexpansion,
                                   MaxJamoExpansionTable *maxjamoexpansion,
                                   UBool                  jamospecial,
@@ -1152,7 +1186,7 @@
   const uint32_t TBASE  = 0x11A8;
   const uint32_t VCOUNT = 21;
   const uint32_t TCOUNT = 28;
-  
+
   uint32_t v = VBASE + VCOUNT - 1;
   uint32_t t = TBASE + TCOUNT - 1;
   uint32_t ce;
@@ -1312,7 +1346,17 @@
     }
 
     UCATableHeader *myData = (UCATableHeader *)dataStart;
-    uprv_memcpy(myData, t->image, sizeof(UCATableHeader));
+    // Please, do reset all the fields!
+    uprv_memset(dataStart, 0, toAllocate);
+    // Make sure we know this is reset
+    myData->magic = UCOL_HEADER_MAGIC;
+    myData->isBigEndian = U_IS_BIG_ENDIAN;
+    myData->charSetFamily = U_CHARSET_FAMILY;
+    uprv_memcpy(myData->formatVersion, ucaDataInfo.formatVersion, sizeof(UVersionInfo));
+    myData->jamoSpecial = t->image->jamoSpecial;
+
+    // Don't copy stuff from UCA header!
+    //uprv_memcpy(myData, t->image, sizeof(UCATableHeader));
 
     myData->contractionSize = contractionsSize;
 
@@ -1343,7 +1387,7 @@
       tableOffset += (uint32_t)(paddedsize(contractionsSize*sizeof(uint32_t)));
     } else {
       myData->contractionIndex = 0;
-      myData->contractionIndex = 0;
+      myData->contractionCEs = 0;
     }
 
     /* copy mapping table */
@@ -1357,11 +1401,13 @@
     // This is debug code to dump the contents of the trie. It needs two functions defined above
     {
       UTrie UCAt = { 0 };
+      uint32_t trieWord;
       utrie_unserialize(&UCAt, dataStart+tableOffset, 9999999, status);
       UCAt.getFoldingOffset = myGetFoldingOffset;
       if(U_SUCCESS(*status)) {
         utrie_enum(&UCAt, NULL, enumRange, NULL);
       }
+      trieWord = UTRIE_GET32_FROM_LEAD(UCAt, 0xDC01) 
     }
 #endif
     tableOffset += paddedsize(mappingSize);
@@ -1476,7 +1522,7 @@
             el.prefixSize = 0;
             el.noOfCEs = 0;
             ucol_setText(colEl, decomp, noOfDec, status);
-            while((el.CEs[el.noOfCEs] = ucol_next(colEl, status)) != UCOL_NULLORDER) {
+            while((el.CEs[el.noOfCEs] = ucol_next(colEl, status)) != (uint32_t)UCOL_NULLORDER) {
               el.noOfCEs++;
             }
           } else {
@@ -1517,7 +1563,7 @@
     tempUCATable *tempTable = uprv_uca_cloneTempTable(t, status);
 
     UCATableHeader *tempData = uprv_uca_assembleTable(tempTable, status);
-    tempColl = ucol_initCollator(tempData, 0, status);
+    tempColl = ucol_initCollator(tempData, 0, t->UCA, status);
     uprv_uca_closeTempTable(tempTable);    
 
     if(U_SUCCESS(*status)) {
@@ -1549,3 +1595,5 @@
 U_NAMESPACE_END
 
 #endif /* #if !UCONFIG_NO_COLLATION */
+
+

Index: ucol_elm.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_elm.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_elm.h	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_elm.h	6 Apr 2004 10:08:53 -0000	1.6
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2000-2001, International Business Machines
+*   Copyright (C) 2000-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -91,7 +91,7 @@
   UHashtable      *prefixLookup;
 } tempUCATable; 
 
-U_CAPI tempUCATable * U_EXPORT2 uprv_uca_initTempTable(UCATableHeader *image, UColOptionSet *opts, const UCollator *UCA, UColCETags initTag, UErrorCode *status);
+U_CAPI tempUCATable * U_EXPORT2 uprv_uca_initTempTable(UCATableHeader *image, UColOptionSet *opts, const UCollator *UCA, UColCETags initTag, UColCETags supplementaryInitTag, UErrorCode *status);
 U_CAPI tempUCATable * U_EXPORT2 uprv_uca_cloneTempTable(tempUCATable *t, UErrorCode *status);
 U_CAPI void U_EXPORT2 uprv_uca_closeTempTable(tempUCATable *t);
 U_CAPI uint32_t U_EXPORT2 uprv_uca_addAnElement(tempUCATable *t, UCAElements *element, UErrorCode *status);

Index: ucol_imp.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_imp.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_imp.h	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_imp.h	6 Apr 2004 10:08:53 -0000	1.6
@@ -54,43 +54,64 @@
  * Substructures are described in the collation design document at
  * http://oss.software.ibm.com/cvs/icu/~checkout~/icuhtml/design/collation/ICU_collation_design.htm
  *
+ * -------------------------------------------------------------
+ *
  * Here is the format of binary collation image.
  *
+ * Physical order of structures:
+ * - header (UCATableHeader)
+ * - options (UColOptionSet)
+ * - expansions (CE[])
+ * - contractions (UChar[contractionSize] + CE[contractionSize])
+ * - serialized UTrie with mappings of code points to CEs
+ * - max expansion tables (CE[endExpansionCECount] + uint8_t[endExpansionCECount])
+ * - two bit sets for backward processing in strcoll (identical prefixes)
+ *   and for backward CE iteration (each set is uint8_t[UCOL_UNSAFECP_TABLE_SIZE])
+ * - UCA constants (UCAConstants)
+ * - UCA contractions (UChar[contractionUCACombosSize][contractionUCACombosWidth])
+ *
+ * UCATableHeader fields:
+ *
  * int32_t size; - image size in bytes
  *
  * Offsets to interesting data. All offsets are in bytes.
  * to get the address add to the header address and cast properly.
- * Offsets are in ascending order if non-zero. 
+ * Some offsets are zero if the corresponding structures are empty.
  *
- * uint32_t options; - offset to default collator options (UColOptionSet *), 1 signed 3-bit value, followed by 7 unsigned 32-bit values, 
- *                     followed by 64 reserved bytes (could be considered 16 32-bit values). See declaration of UColOptionSet for more details
+ * Tailoring binaries that only set options and contain no mappings etc.
+ * will have all offsets 0 except for the options and expansion offsets,
+ * which give the position and length of the options array.
  *
- * uint32_t UCAConsts; - only used in UCA image - structure which holds values for indirect positioning and implicit ranges
- *                       See declaration of UCAConstants structure. This is a field of 37 unsigned 32-bit values used to store 
+ * uint32_t options; - offset to default collator options (UColOptionSet *),
+ *                     a set of 32-bit values. See declaration of UColOptionSet for more details
+ *
+ * uint32_t UCAConsts; - only used (!=0) in UCA image - structure which holds values for indirect positioning and implicit ranges
+ *                       See declaration of UCAConstants structure. This is a set of unsigned 32-bit values used to store 
  *                       important constant values that are defined in the UCA and used for building and runtime.
  *
- * uint32_t contractionUCACombos; - only used in UCA image - list of UCA contractions. This is a zero terminated array of UChar[3],
+ * uint32_t contractionUCACombos; - only used (!=0) in UCA image - list of UCA contractions. This is a zero terminated array of UChar[contractionUCACombosWidth],
  *                                  containing contractions from the UCA. These are needed in the build process to copy UCA contractions
  *                                  in case the base contraction symbol is tailored.
  *
- * uint32_t unusedReserved1; -  reserved for future use 
+ * uint32_t magic; - must contain UCOL_HEADER_MAGIC (formatVersion 2.3)
  *
  * uint32_t mappingPosition;  - offset to UTrie (const uint8_t *mappingPosition). This is a serialized UTrie and should be treated as such. 
  *                              Used as a primary lookup table for collation elements.
  *
- * uint32_t expansion;  - offset to expansion table (uint32_t *expansion). This is an array of expansion CEs. 
+ * uint32_t expansion;  - offset to expansion table (uint32_t *expansion). This is an array of expansion CEs. Never 0.
  *
  * uint32_t contractionIndex; - offset to contraction table (UChar *contractionIndex). Used to look up contraction sequences. Contents
- *                              are aligned with the contents of contractionCEs table.
+ *                              are aligned with the contents of contractionCEs table. 0 if no contractions.
  *
  * uint32_t contractionCEs;  - offset to resulting contraction CEs (uint32_t *contractionCEs). When a contraction is resolved in the
  *                             in the contractionIndex table, the resulting index is used to look up corresponding CE in this table. 
- *
+ *                             0 if no contractions.
  * uint32_t contractionSize; - size of contraction table in elements (both Index and CEs). 
  *
  * Tables described below are used for Boyer-Moore searching algorithm - they define the size of longest expansion
  * and last CEs in expansions.
- * uint32_t endExpansionCE; - offset to array of last collation element in expansion (uint32_t *). .
+ * uint32_t endExpansionCE; - offset to array of last collation element in expansion (uint32_t *).
+ *                            Never 0.
  * uint32_t expansionCESize; - array of maximum expansion sizes (uint8_t *)
  * int32_t  endExpansionCECount; - size of endExpansionCE. See UCOL_GETMAXEXPANSION
  *                                 for the usage model
@@ -99,27 +120,31 @@
  * uint32_t unsafeCP; - hash table of unsafe code points (uint8_t *). See ucol_unsafeCP function.
  * uint32_t contrEndCP; - hash table of final code points in contractions (uint8_t *). See ucol_contractionEndCP.              
  *
- * int32_t CEcount; - currently unused
- *
+ * int32_t contractionUCACombosSize; - number of UChar[contractionUCACombosWidth] in contractionUCACombos
+ *                                     (formatVersion 2.3)
  * UBool jamoSpecial; - Jamo special indicator (uint8_t). If TRUE, Jamos are special, so we cannot use simple Hangul decomposition.
- * uint8_t padding[3]; - padding 3 uint8_t 
+ * UBool isBigEndian; - endianness of this collation binary (formatVersion 2.3)
+ * uint8_t charSetFamily; - charset family of this collation binary (formatVersion 2.3)
+ * uint8_t contractionUCACombosWidth; - number of UChars per UCA contraction in contractionUCACombos (formatVersion 2.3)
  *
  * Various version fields
  * UVersionInfo version; - version 4 uint8_t
  * UVersionInfo UCAVersion;  - version 4 uint8_t
  * UVersionInfo UCDVersion;  - version 4 uint8_t
+ * UVersionInfo formatVersion; - version of the format of the collation binary
+ *                               same formatVersion as in ucadata.icu's UDataInfo header
+ *                               (formatVersion 2.3)
  *
- * char charsetName[32];  - currently unused 32 uint8_t
- * uint8_t reserved[56];  - currently unused 64 uint8_t
+ * uint8_t reserved[84];  - currently unused
  *
- * This header is followed by data addressed by offsets in the header. 
+ * -------------------------------------------------------------
  *
  * Inverse UCA is used for constructing collators from rules. It is always an individual file
  * and always has a UDataInfo header. 
  * here is the structure:
  * 
  * uint32_t byteSize; - size of inverse UCA image in bytes
- * uint32_t tableSize; - size of inverse table (number of (inverse elements + 2)*3
+ * uint32_t tableSize; - length of inverse table (number of uint32_t[3] rows)
  * uint32_t contsSize; - size of continuation table (number of UChars in table)
  *
  * uint32_t table; - offset to inverse table (uint32_t *)
@@ -135,6 +160,9 @@
  * Header is followed by the table and continuation table.
 */
 
+/* let us know whether reserved fields are reset to zero or junked */
+#define UCOL_HEADER_MAGIC 0x20030618
+
 /* UDataInfo for UCA mapping table */
 static const UDataInfo ucaDataInfo={
     sizeof(UDataInfo),
@@ -151,7 +179,8 @@
     /*            to int32_t in UColOptionSet */
     /* 05/13/2003 This one also updated since we added UCA and UCD versions */
     /*            to header */
-    {2, 2, 0, 0},                 /* formatVersion                */
+    /* 09/11/2003 Adding information required by data swapper */
+    {2, 3, 0, 0},                 /* formatVersion                */
     {3, 0, 0, 0}                  /* dataVersion = Unicode Version*/
 };
 
@@ -537,6 +566,7 @@
     UCOL_BYTE_FIRST_TAILORED = 0x04,
     UCOL_BYTE_COMMON = 0x05,
     UCOL_BYTE_FIRST_UCA = UCOL_BYTE_COMMON,
+    UCOL_CODAN_PLACEHOLDER = 0x24,
     UCOL_BYTE_LAST_LATIN_PRIMARY = 0x4C,
     UCOL_BYTE_FIRST_NON_LATIN_PRIMARY = 0x4D,
     UCOL_BYTE_UNSHIFTED_MAX = 0xFF
@@ -635,6 +665,9 @@
     LONG_PRIMARY_TAG = 12,   /* This is a three byte primary with starting secondaries and tertiaries */
                              /* It fits in a single 32 bit CE and is used instead of expansion to save */
                              /* space without affecting the performance (hopefully) */
+                             
+	DIGIT_TAG = 13,			/* COllate Digits As Numbers (CODAN) implementation */
+	
     CE_TAGS_COUNT
 } UColCETags;
 
@@ -653,8 +686,9 @@
       /*UColAttributeValue*/ int32_t caseLevel;         /* do we have an extra case level */
       /*UColAttributeValue*/ int32_t normalizationMode; /* attribute for normalization */
       /*UColAttributeValue*/ int32_t strength;          /* attribute for strength */
-      /*UColAttributeValue*/ int32_t hiraganaQ;         /* attribuge for special Hiragana */
-      uint8_t reserved[64];                 /* for future use */
+      /*UColAttributeValue*/ int32_t hiraganaQ;         /* attribute for special Hiragana */
+      /*UColAttributeValue*/ int32_t numericCollation;  /* attribute for numeric collation */
+      uint32_t reserved[15];                 /* for future use */
 } UColOptionSet;
 
 typedef struct {
@@ -702,7 +736,7 @@
       uint32_t options; /* these are the default options for the collator */
       uint32_t UCAConsts; /* structure which holds values for indirect positioning and implicit ranges */
       uint32_t contractionUCACombos;        /* this one is needed only for UCA, to copy the appropriate contractions */
-      uint32_t unusedReserved1;         /* reserved for future use */
+      uint32_t magic;            /* magic number - lets us know whether reserved data is reset or junked */
       uint32_t mappingPosition;  /* const uint8_t *mappingPosition; */
       uint32_t expansion;        /* uint32_t *expansion;            */
       uint32_t contractionIndex; /* UChar *contractionIndex;        */
@@ -721,14 +755,17 @@
       uint32_t contrEndCP;          /* hash table of final code points  */
                                     /*   in contractions.               */
 
-      int32_t CEcount;
+      int32_t contractionUCACombosSize;     /* number of UCA contraction items. */
+                                            /*Length is contractionUCACombosSize*contractionUCACombosWidth*sizeof(UChar) */
       UBool jamoSpecial;                    /* is jamoSpecial */
-      uint8_t padding[3];                   /* for guaranteed alignment */
+      UBool isBigEndian;                    /* is this data big endian? from the UDataInfo header*/
+      uint8_t charSetFamily;                /* what is the charset family of this data from the UDataInfo header*/
+      uint8_t contractionUCACombosWidth;    /* width of UCA combos field */
       UVersionInfo version;
       UVersionInfo UCAVersion;              /* version of the UCA, read from file */
       UVersionInfo UCDVersion;              /* UCD version, obtained by u_getUnicodeVersion */
-      char charsetName[32];                 /* for charset CEs */
-      uint8_t reserved[56];                 /* for future use */
+      UVersionInfo formatVersion;           /* format version from the UDataInfo header */
+      uint8_t reserved[84];                 /* for future use */
 } UCATableHeader;
 
 #define U_UNKNOWN_STATE 0
@@ -862,6 +899,7 @@
     UColAttributeValue normalizationMode; /* attribute for normalization */
     UColAttributeValue strength;          /* attribute for strength */
     UColAttributeValue hiraganaQ;         /* attribute for Hiragana */
+    UColAttributeValue numericCollation;
     UBool variableTopValueisDefault;
     UBool frenchCollationisDefault;
     UBool alternateHandlingisDefault; /* attribute for handling variable elements*/
@@ -870,6 +908,7 @@
     UBool normalizationModeisDefault; /* attribute for normalization */
     UBool strengthisDefault;          /* attribute for strength */
     UBool hiraganaQisDefault;         /* attribute for Hiragana */
+    UBool numericCollationisDefault;
     UBool hasRealData;                /* some collators have only options, like French, no rules */
                                       /* to speed up things, we use the UCA image, but we don't want it */
                                       /* to run around */
@@ -893,6 +932,7 @@
     uint8_t tertiaryBottomCount;
 
     UDataInfo dataInfo;               /* Data info of UCA table */
+    const UCollator *UCA;
 
 };
 
@@ -905,7 +945,7 @@
 UCollator* ucol_initUCA(UErrorCode *status);
 
 U_CFUNC
-UCollator* ucol_initCollator(const UCATableHeader *image, UCollator *fillIn, UErrorCode *status);
+UCollator* ucol_initCollator(const UCATableHeader *image, UCollator *fillIn, const UCollator *UCA, UErrorCode *status);
 
 U_CFUNC
 void ucol_setOptionsFromHeader(UCollator* result, UColOptionSet * opts, UErrorCode *status);
@@ -926,14 +966,24 @@
 U_CAPI UBool U_EXPORT2 ucol_isTailored(const UCollator *coll, const UChar u, UErrorCode *status);
 
 U_CAPI const InverseUCATableHeader* U_EXPORT2 ucol_initInverseUCA(UErrorCode *status);
-U_CAPI int32_t U_EXPORT2 ucol_inv_getNextCE(uint32_t CE, uint32_t contCE,
-                                            uint32_t *nextCE, uint32_t *nextContCE,
-                                            uint32_t strength);
-U_CAPI int32_t U_EXPORT2 ucol_inv_getPrevCE(uint32_t CE, uint32_t contCE,
-                                            uint32_t *prevCE, uint32_t *prevContCE,
-                                            uint32_t strength);
+
 U_CAPI void U_EXPORT2 
-uprv_uca_initImplicitConstants(uint32_t baseByte);
+uprv_uca_initImplicitConstants(int32_t minPrimary, int32_t maxPrimary, UErrorCode *status);
+
+U_CAPI uint32_t U_EXPORT2
+uprv_uca_getImplicitFromRaw(UChar32 cp);
+
+U_CAPI uint32_t U_EXPORT2
+uprv_uca_getImplicitPrimary(UChar32 cp);
+
+U_CAPI UChar32 U_EXPORT2
+uprv_uca_getRawFromImplicit(uint32_t implicit);
+
+U_CAPI UChar32 U_EXPORT2
+uprv_uca_getRawFromCodePoint(UChar32 i);
+
+U_CAPI UChar32 U_EXPORT2
+uprv_uca_getCodePointFromRaw(UChar32 i);
 
 /** Check whether two collators are equal. Collators are considered equal if they
  *  will sort strings the same. This means that both the current attributes and the
@@ -945,6 +995,8 @@
 U_CAPI UBool U_EXPORT2
 ucol_equals(const UCollator *source, const UCollator *target);
 
+
+
 #ifdef XP_CPLUSPLUS
 /*
  *  Test whether a character is potentially "unsafe" for use as a collation
@@ -980,4 +1032,3 @@
 #endif /* #if !UCONFIG_NO_COLLATION */
 
 #endif
-

Index: ucol_tok.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_tok.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ucol_tok.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ ucol_tok.cpp	6 Apr 2004 10:08:54 -0000	1.6
@@ -181,11 +181,15 @@
     //for post-context
     start = pos+1;
     stop  = ((pos+U_PARSE_CONTEXT_LEN)<= rulesLen )? (pos+(U_PARSE_CONTEXT_LEN-1)) : 
-                                                            u_strlen(rules);
+                                                            rulesLen;
 
-    u_memcpy(parseError->postContext,rules+start,stop-start);
-    //null terminate the buffer
-    parseError->postContext[stop-start]= 0;
+    if(start < stop) {
+      u_memcpy(parseError->postContext,rules+start,stop-start);
+      //null terminate the buffer
+      parseError->postContext[stop-start]= 0;
+    } else {
+      parseError->postContext[0] = 0;
+    }
 }
 
 static
@@ -212,13 +216,16 @@
   case UCOL_STRENGTH:
     opts->strength = value;
     break;
+  case UCOL_NUMERIC_COLLATION:
+  	opts->numericCollation = value;
+  	break;
   case UCOL_ATTRIBUTE_COUNT:
   default:
     break;
   }
 }
 
-#define UTOK_OPTION_COUNT 19
+#define UTOK_OPTION_COUNT 20
 
 static UBool didInit = FALSE;
 /* we can be strict, or we can be lenient */
@@ -265,6 +272,7 @@
 U_STRING_DECL(option_16,    "last",           4);
 U_STRING_DECL(option_17,    "optimize",       8);
 U_STRING_DECL(option_18,    "suppressContractions",         20);
+U_STRING_DECL(option_19,    "numericOrdering",				15);
 
 
 /*
@@ -320,6 +328,30 @@
   {suboption_17, 8, UCOL_PRIMARY},
 };
 
+enum OptionNumber {
+  OPTION_ALTERNATE_HANDLING = 0,
+    OPTION_FRENCH_COLLATION,
+    OPTION_CASE_LEVEL,
+    OPTION_CASE_FIRST,
+    OPTION_NORMALIZATION_MODE,
+    OPTION_HIRAGANA_QUATERNARY,
+    OPTION_STRENGTH,
+    OPTION_NUMERIC_COLLATION,
+    OPTION_NORMAL_OPTIONS_LIMIT = OPTION_NUMERIC_COLLATION,
+    OPTION_VARIABLE_TOP,
+    OPTION_REARRANGE,
+    OPTION_BEFORE,
+    OPTION_TOP,
+    OPTION_FIRST,
+    OPTION_LAST,
+    OPTION_OPTIMIZE,
+    OPTION_SUPPRESS_CONTRACTIONS,
+    OPTION_UNDEFINED,
+    OPTION_SCRIPT_ORDER,
+    OPTION_CHARSET_NAME,
+    OPTION_CHARSET
+} ;
+
 static const ucolTokOption rulesOptions[UTOK_OPTION_COUNT] = {
  /*00*/ {option_02,  9, alternateSub, 2, UCOL_ALTERNATE_HANDLING}, /*"alternate" */
  /*01*/ {option_03,  9, frenchSub, 1, UCOL_FRENCH_COLLATION}, /*"backwards"      */
@@ -328,18 +360,19 @@
  /*04*/ {option_06, 13, onOffSub, 2, UCOL_NORMALIZATION_MODE}, /*"normalization" */
  /*05*/ {option_13, 9, onOffSub, 2, UCOL_HIRAGANA_QUATERNARY_MODE}, /*"hiraganaQ" */
  /*06*/ {option_14, 8, strengthSub, 5, UCOL_STRENGTH}, /*"strength" */
- /*07*/ {option_04, 12, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"variable top"   */
- /*08*/ {option_01,  9, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"rearrange"      */
- /*09*/ {option_12,  6, beforeSub, 3, UCOL_ATTRIBUTE_COUNT}, /*"before"    */
- /*10*/ {option_05,  3, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"top"            */
- /*11*/ {option_15,  5, firstLastSub, 7, UCOL_ATTRIBUTE_COUNT}, /*"first" */
- /*12*/ {option_16,  4, firstLastSub, 7, UCOL_ATTRIBUTE_COUNT}, /*"last" */
- /*13*/ {option_17,  8, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"optimize"      */
- /*14*/ {option_18, 20, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"suppressContractions"      */
- /*15*/ {option_00,  9, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"undefined"      */
- /*16*/ {option_09, 11, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"scriptOrder"    */
- /*17*/ {option_10, 11, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"charsetname"    */
- /*18*/ {option_11,  7, NULL, 0, UCOL_ATTRIBUTE_COUNT}  /*"charset"        */
+ /*07*/ {option_19, 15, onOffSub, 2, UCOL_NUMERIC_COLLATION},  /*"numericOrdering"*/ 
+ /*08*/ {option_04, 12, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"variable top"   */
+ /*09*/ {option_01,  9, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"rearrange"      */
+ /*10*/ {option_12,  6, beforeSub, 3, UCOL_ATTRIBUTE_COUNT}, /*"before"    */
+ /*11*/ {option_05,  3, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"top"            */
+ /*12*/ {option_15,  5, firstLastSub, 7, UCOL_ATTRIBUTE_COUNT}, /*"first" */
+ /*13*/ {option_16,  4, firstLastSub, 7, UCOL_ATTRIBUTE_COUNT}, /*"last" */
+ /*14*/ {option_17,  8, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"optimize"      */
+ /*15*/ {option_18, 20, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"suppressContractions"      */
+ /*16*/ {option_00,  9, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"undefined"      */
+ /*17*/ {option_09, 11, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"scriptOrder"    */
+ /*18*/ {option_10, 11, NULL, 0, UCOL_ATTRIBUTE_COUNT}, /*"charsetname"    */
+ /*19*/ {option_11,  7, NULL, 0, UCOL_ATTRIBUTE_COUNT}  /*"charset"        */
 };
 
 static
@@ -406,6 +439,7 @@
     U_STRING_INIT(option_16, "last",           4);
     U_STRING_INIT(option_17, "optimize",       8);
     U_STRING_INIT(option_18, "suppressContractions",         20);
+	U_STRING_INIT(option_19, "numericOrdering",      15);
     didInit = TRUE;
   }
 }
@@ -558,65 +592,85 @@
 
   if(i < 0) {
     *status = U_ILLEGAL_ARGUMENT_ERROR;
-  } else if(i<7) {
-    if(optionArg) {
-      for(j = 0; j<rulesOptions[i].subSize; j++) {
-        if(u_strncmpNoCase(optionArg, rulesOptions[i].subopts[j].subName, rulesOptions[i].subopts[j].subLen) == 0) {
-          ucol_uprv_tok_setOptionInImage(src->opts, rulesOptions[i].attr, rulesOptions[i].subopts[j].attrVal);
-          result =  UCOL_TOK_SUCCESS;
+  } else {
+    int32_t noOpenBraces = 1;
+    switch(i) {
+    case OPTION_ALTERNATE_HANDLING:
+    case OPTION_FRENCH_COLLATION:
+    case OPTION_CASE_LEVEL:
+    case OPTION_CASE_FIRST:
+    case OPTION_NORMALIZATION_MODE:
+    case OPTION_HIRAGANA_QUATERNARY:
+    case OPTION_STRENGTH:
+    case OPTION_NUMERIC_COLLATION:
+      if(optionArg) {
+        for(j = 0; j<rulesOptions[i].subSize; j++) {
+          if(u_strncmpNoCase(optionArg, rulesOptions[i].subopts[j].subName, rulesOptions[i].subopts[j].subLen) == 0) {
+            ucol_uprv_tok_setOptionInImage(src->opts, rulesOptions[i].attr, rulesOptions[i].subopts[j].attrVal);
+            result =  UCOL_TOK_SUCCESS;
+          }
         }
+      } 
+      if(result == 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
       }
-    } 
-    if(result == 0) {
-      *status = U_ILLEGAL_ARGUMENT_ERROR;
-    }
-  } else if(i == 7) { /* variable top */
-    result = UCOL_TOK_SUCCESS | UCOL_TOK_VARIABLE_TOP;
-  } else if(i == 8) {  /*rearange */
-    result = UCOL_TOK_SUCCESS;
-  } else if(i == 9) {  /*before*/
-    if(optionArg) {
+      break;
+    case OPTION_VARIABLE_TOP:
+      result = UCOL_TOK_SUCCESS | UCOL_TOK_VARIABLE_TOP;
+      break;
+    case OPTION_REARRANGE:
+      result = UCOL_TOK_SUCCESS;
+      break;
+    case OPTION_BEFORE:
+      if(optionArg) {
+        for(j = 0; j<rulesOptions[i].subSize; j++) {
+          if(u_strncmpNoCase(optionArg, rulesOptions[i].subopts[j].subName, rulesOptions[i].subopts[j].subLen) == 0) {
+          result = UCOL_TOK_SUCCESS | rulesOptions[i].subopts[j].attrVal + 1;
+          }
+        }
+      }
+      if(result == 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+      }
+      break;
+    case OPTION_TOP: /* we are going to have an array with structures of limit CEs */
+      /* index to this array will be src->parsedToken.indirectIndex*/
+      src->parsedToken.indirectIndex = 0;
+      result = UCOL_TOK_SUCCESS | UCOL_TOK_TOP;
+      break;
+    case OPTION_FIRST:
+    case OPTION_LAST: /* first, last */
       for(j = 0; j<rulesOptions[i].subSize; j++) {
         if(u_strncmpNoCase(optionArg, rulesOptions[i].subopts[j].subName, rulesOptions[i].subopts[j].subLen) == 0) {
-        result = UCOL_TOK_SUCCESS | rulesOptions[i].subopts[j].attrVal + 1;
+          // the calculation below assumes that OPTION_FIRST and OPTION_LAST are at i and i+1 and that the first
+          // element of indirect boundaries is reserved for top.
+          src->parsedToken.indirectIndex = (uint16_t)(i-OPTION_FIRST+1+j*2);
+          result =  UCOL_TOK_SUCCESS | UCOL_TOK_TOP;;
         }
       }
-    }
-    if(result == 0) {
-      *status = U_ILLEGAL_ARGUMENT_ERROR;
-    }
-    
-  } else if(i == 10) {  /*top */ /* we are going to have an array with structures of limit CEs */
-    /* index to this array will be src->parsedToken.indirectIndex*/
-    src->parsedToken.indirectIndex = 0;
-    result = UCOL_TOK_SUCCESS | UCOL_TOK_TOP;
-  } else if(i == 11 || i ==12) { /* first, last */
-    for(j = 0; j<rulesOptions[i].subSize; j++) {
-      if(u_strncmpNoCase(optionArg, rulesOptions[i].subopts[j].subName, rulesOptions[i].subopts[j].subLen) == 0) {
-        src->parsedToken.indirectIndex = (uint16_t)(i-10+j*2);         
-        result =  UCOL_TOK_SUCCESS | UCOL_TOK_TOP;;
+      if(result == 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
       }
-    }
-    if(result == 0) {
-      *status = U_ILLEGAL_ARGUMENT_ERROR;
-    }
-  } else if(i == 13 || i == 14) { // copy and remove are handled before normalization
-    // we need to move end here
-    int32_t noOpenBraces = 1;
-    src->current++; // skip opening brace
-    while(src->current < src->end && noOpenBraces != 0) {
-      if(*src->current == 0x005b) {
-        noOpenBraces++;
-      } else if(*src->current == 0x005D) { // closing brace
-        noOpenBraces--;
+      break;
+    case OPTION_OPTIMIZE:
+    case OPTION_SUPPRESS_CONTRACTIONS:  // copy and remove are handled before normalization
+      // we need to move end here
+      src->current++; // skip opening brace
+      while(src->current < src->end && noOpenBraces != 0) {
+        if(*src->current == 0x005b) {
+          noOpenBraces++;
+        } else if(*src->current == 0x005D) { // closing brace
+          noOpenBraces--;
+        }
+        src->current++;
       }
-      src->current++;
+      result = UCOL_TOK_SUCCESS;
+      break;
+    default:
+      *status = U_UNSUPPORTED_ERROR;
+      break;
     }
-    result = UCOL_TOK_SUCCESS;
-  } else {
-    *status = U_UNSUPPORTED_ERROR;
   }
-  //src->current = u_strchr(src->current, 0x005d /*']'*/);
   src->current = u_memchr(src->current, 0x005d, src->end-src->current);
   return result;
 }
@@ -1116,58 +1170,101 @@
     baseContCE = 0;
   }
 
-  invPos = ucol_inv_getPrevCE(baseCE, baseContCE, &CE, &SecondCE, strength);
 
-  uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
-  uint32_t ch = CETable[3*invPos+2];
+  UCAConstants *consts = (UCAConstants *)((uint8_t *)src->UCA->image + src->UCA->image->UCAConsts);
+  uint32_t ch = 0;
+  uint32_t expandNext = 0;
+  UColToken key;
 
-  if((ch &  UCOL_INV_SIZEMASK) != 0) {
-    uint16_t *conts = (uint16_t *)((uint8_t *)src->invUCA+src->invUCA->conts);
-    uint32_t offset = (ch & UCOL_INV_OFFSETMASK);
-    ch = conts[offset];
-  }      
-  *src->extraCurrent++ = (UChar)ch;
-  src->parsedToken.charsOffset = (uint32_t)(src->extraCurrent - src->source - 1);
-  src->parsedToken.charsLen = 1;
+  if((baseCE & 0xFF000000) >= (consts->UCA_PRIMARY_IMPLICIT_MIN<<24) && (baseCE & 0xFF000000) <= (consts->UCA_PRIMARY_IMPLICIT_MAX<<24) ) { /* implicits - */ 
+      uint32_t primary = baseCE & UCOL_PRIMARYMASK | (baseContCE & UCOL_PRIMARYMASK) >> 16;
+      uint32_t raw = uprv_uca_getRawFromImplicit(primary);
+      ch = uprv_uca_getCodePointFromRaw(raw-1);
+      uint32_t primaryCE = uprv_uca_getImplicitFromRaw(raw-1);
+      CE = primaryCE & UCOL_PRIMARYMASK | 0x0505;
+      SecondCE = (primaryCE << 16) & UCOL_PRIMARYMASK | UCOL_CONTINUATION_MARKER;
 
-  // We got an UCA before. However, this might have been tailored.
-  // example:
-  // &\u30ca = \u306a
-  // &[before 3]\u306a<<<\u306a|\u309d
+      src->parsedToken.charsOffset = (uint32_t)(src->extraCurrent - src->source);
+      *src->extraCurrent++ = 0xFFFE;
+      *src->extraCurrent++ = (UChar)ch;
+      src->parsedToken.charsLen++;
+
+      key.source = (src->parsedToken.charsLen/**newCharsLen*/ << 24) | src->parsedToken.charsOffset/**charsOffset*/;
+      key.rulesToParse = src->source;
+
+      //sourceToken = (UColToken *)uhash_iget(src->tailored, (int32_t)key);
+      sourceToken = (UColToken *)uhash_get(src->tailored, &key);
+
+      if(sourceToken == NULL) {
+          src->lh[src->resultLen].baseCE = CE & 0xFFFFFF3F;
+          if(isContinuation(SecondCE)) {
+            src->lh[src->resultLen].baseContCE = SecondCE;
+          } else {
+            src->lh[src->resultLen].baseContCE = 0;
+          }
+          src->lh[src->resultLen].nextCE = 0;
+          src->lh[src->resultLen].nextContCE = 0;
+          src->lh[src->resultLen].previousCE = 0;
+          src->lh[src->resultLen].previousContCE = 0;
+
+          src->lh[src->resultLen].indirect = FALSE;
+
+          sourceToken = ucol_tok_initAReset(src, 0, &expandNext, parseError, status);   
+      }
+
+  } else {
+      invPos = ucol_inv_getPrevCE(src, baseCE, baseContCE, &CE, &SecondCE, strength);
+
+      uint32_t *CETable = (uint32_t *)((uint8_t *)src->invUCA+src->invUCA->table);
+      ch = CETable[3*invPos+2];
+
+      if((ch &  UCOL_INV_SIZEMASK) != 0) {
+        uint16_t *conts = (uint16_t *)((uint8_t *)src->invUCA+src->invUCA->conts);
+        uint32_t offset = (ch & UCOL_INV_OFFSETMASK);
+        ch = conts[offset];
+      }      
+
+      *src->extraCurrent++ = (UChar)ch;
+      src->parsedToken.charsOffset = (uint32_t)(src->extraCurrent - src->source - 1);
+      src->parsedToken.charsLen = 1;
+
+      // We got an UCA before. However, this might have been tailored.
+      // example:
+      // &\u30ca = \u306a
+      // &[before 3]\u306a<<<\u306a|\u309d
   
   
-  // uint32_t key = (*newCharsLen << 24) | *charsOffset;
-  UColToken key;
-  uint32_t expandNext = 0;
-  key.source = (src->parsedToken.charsLen/**newCharsLen*/ << 24) | src->parsedToken.charsOffset/**charsOffset*/;
-  key.rulesToParse = src->source;
+      // uint32_t key = (*newCharsLen << 24) | *charsOffset;
+      key.source = (src->parsedToken.charsLen/**newCharsLen*/ << 24) | src->parsedToken.charsOffset/**charsOffset*/;
+      key.rulesToParse = src->source;
 
-  //sourceToken = (UColToken *)uhash_iget(src->tailored, (int32_t)key);
-  sourceToken = (UColToken *)uhash_get(src->tailored, &key);
+      //sourceToken = (UColToken *)uhash_iget(src->tailored, (int32_t)key);
+      sourceToken = (UColToken *)uhash_get(src->tailored, &key);
   
-  // if we found a tailored thing, we have to use the UCA value and construct 
-  // a new reset token with constructed name
-  if(sourceToken != NULL && sourceToken->strength != UCOL_TOK_RESET) {
-    // character to which we want to anchor is already tailored. 
-    // We need to construct a new token which will be the anchor
-    // point
-    *(src->extraCurrent-1) = 0xFFFE;
-    *src->extraCurrent++ = (UChar)ch;
-    src->parsedToken.charsLen++;
-    src->lh[src->resultLen].baseCE = CE & 0xFFFFFF3F;
-    if(isContinuation(SecondCE)) {
-      src->lh[src->resultLen].baseContCE = SecondCE;
-    } else {
-      src->lh[src->resultLen].baseContCE = 0;
-    }
-    src->lh[src->resultLen].nextCE = 0;
-    src->lh[src->resultLen].nextContCE = 0;
-    src->lh[src->resultLen].previousCE = 0;
-    src->lh[src->resultLen].previousContCE = 0;
+      // if we found a tailored thing, we have to use the UCA value and construct 
+      // a new reset token with constructed name
+      if(sourceToken != NULL && sourceToken->strength != UCOL_TOK_RESET) {
+        // character to which we want to anchor is already tailored. 
+        // We need to construct a new token which will be the anchor
+        // point
+        *(src->extraCurrent-1) = 0xFFFE;
+        *src->extraCurrent++ = (UChar)ch;
+        src->parsedToken.charsLen++;
+        src->lh[src->resultLen].baseCE = CE & 0xFFFFFF3F;
+        if(isContinuation(SecondCE)) {
+          src->lh[src->resultLen].baseContCE = SecondCE;
+        } else {
+          src->lh[src->resultLen].baseContCE = 0;
+        }
+        src->lh[src->resultLen].nextCE = 0;
+        src->lh[src->resultLen].nextContCE = 0;
+        src->lh[src->resultLen].previousCE = 0;
+        src->lh[src->resultLen].previousContCE = 0;
 
-    src->lh[src->resultLen].indirect = FALSE;
+        src->lh[src->resultLen].indirect = FALSE;
 
-    sourceToken = ucol_tok_initAReset(src, 0, &expandNext, parseError, status);   
+        sourceToken = ucol_tok_initAReset(src, 0, &expandNext, parseError, status);   
+      }
   }
 
   return sourceToken;
@@ -1443,8 +1540,17 @@
             uint32_t baseContCE = ucolIndirectBoundaries[src->parsedToken.indirectIndex].startContCE;//&0xFFFFFF3F;
             uint32_t CE = UCOL_NOT_FOUND, SecondCE = UCOL_NOT_FOUND;
 
-            /*int32_t invPos = ucol_inv_getPrevCE(baseCE, baseContCE, &CE, &SecondCE, strength);*/
-            ucol_inv_getPrevCE(baseCE, baseContCE, &CE, &SecondCE, strength);
+            UCAConstants *consts = (UCAConstants *)((uint8_t *)src->UCA->image + src->UCA->image->UCAConsts);
+            if((baseCE & 0xFF000000) >= (consts->UCA_PRIMARY_IMPLICIT_MIN<<24) && (baseCE & 0xFF000000) <= (consts->UCA_PRIMARY_IMPLICIT_MAX<<24) ) { /* implicits - */ 
+              uint32_t primary = baseCE & UCOL_PRIMARYMASK | (baseContCE & UCOL_PRIMARYMASK) >> 16;
+              uint32_t raw = uprv_uca_getRawFromImplicit(primary);
+              uint32_t primaryCE = uprv_uca_getImplicitFromRaw(raw-1);
+              CE = primaryCE & UCOL_PRIMARYMASK | 0x0505;
+              SecondCE = (primaryCE << 16) & UCOL_PRIMARYMASK | UCOL_CONTINUATION_MARKER;
+            } else {
+                /*int32_t invPos = ucol_inv_getPrevCE(baseCE, baseContCE, &CE, &SecondCE, strength);*/
+                ucol_inv_getPrevCE(src, baseCE, baseContCE, &CE, &SecondCE, strength);
+            }
 
             ListList[src->resultLen].baseCE = CE;
             ListList[src->resultLen].baseContCE = SecondCE;
@@ -1525,7 +1631,7 @@
   return src->resultLen;
 }
 
-void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, UCollator *UCA, UErrorCode *status) {
+void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, const UCollator *UCA, UErrorCode *status) {
   uint32_t nSize = 0;
   uint32_t estimatedSize = (2*rulesLength+UCOL_TOK_EXTRA_RULE_SPACE_SIZE);
   if(U_FAILURE(*status)) {
@@ -1546,7 +1652,7 @@
       // while((openBrace = u_strchr(openBrace, 0x005B)) != NULL) { // find open braces
       //optionNumber = ucol_uprv_tok_readOption(openBrace+1, rules+rulesLength, &setStart);
       optionNumber = ucol_uprv_tok_readOption(rules+i+1, rules+rulesLength, &setStart);
-      if(optionNumber == 13) { /* copy - parts of UCA to tailoring */
+      if(optionNumber == OPTION_OPTIMIZE) { /* copy - parts of UCA to tailoring */
         USet *newSet = ucol_uprv_tok_readAndSetUnicodeSet(setStart, rules+rulesLength, status);
         if(U_SUCCESS(*status)) {
           if(src->copySet == NULL) {
@@ -1558,7 +1664,7 @@
         } else {
           return;
         }
-      } else if(optionNumber == 14) {
+      } else if(optionNumber == OPTION_SUPPRESS_CONTRACTIONS) {
         USet *newSet = ucol_uprv_tok_readAndSetUnicodeSet(setStart, rules+rulesLength, status);
         if(U_SUCCESS(*status)) {
           if(src->removeSet == NULL) {
@@ -1582,6 +1688,7 @@
       *status = U_MEMORY_ALLOCATION_ERROR;
       return;
   }
+  uprv_memset(src->source, 0, estimatedSize*sizeof(UChar));
   nSize = unorm_normalize(rules, rulesLength, UNORM_NFD, 0, src->source, estimatedSize, status);
   if(nSize > estimatedSize || *status == U_BUFFER_OVERFLOW_ERROR) {
     *status = U_ZERO_ERROR;
@@ -1596,7 +1703,7 @@
   src->current = src->source;
   src->end = src->source+nSize;
   src->sourceCurrent = src->source;
-  src->extraCurrent = src->end;
+  src->extraCurrent = src->end+1; // Preserve terminating zero in the rule string so that option scanning works correctly
   src->extraEnd = src->source+estimatedSize; //src->end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
   src->varTop = NULL;
   src->UCA = UCA;
@@ -1638,6 +1745,7 @@
       *status = U_MEMORY_ALLOCATION_ERROR;
       return;
   }
+  uprv_memset(src->lh, 0, src->listCapacity*sizeof(UColTokListHeader));
   src->resultLen = 0;
 
   UCAConstants *consts = (UCAConstants *)((uint8_t *)src->UCA->image + src->UCA->image->UCAConsts);
@@ -1698,3 +1806,4 @@
 }
 
 #endif /* #if !UCONFIG_NO_COLLATION */
+

Index: ucol_tok.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_tok.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ucol_tok.h	10 Sep 2003 02:42:24 -0000	1.4
+++ ucol_tok.h	6 Apr 2004 10:08:54 -0000	1.5
@@ -151,7 +151,7 @@
                                     UErrorCode *status);
 
 U_CFUNC
-void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, UCollator *UCA, UErrorCode *status);
+void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, const UCollator *UCA, UErrorCode *status);
 
 U_CFUNC void ucol_tok_closeTokenList(UColTokenParser *src);
 
@@ -164,6 +164,14 @@
 ucol_tok_getNextArgument(const UChar *start, const UChar *end, 
                                UColAttribute *attrib, UColAttributeValue *value, 
                                UErrorCode *status);
+U_CAPI int32_t U_EXPORT2 ucol_inv_getNextCE(const UColTokenParser *src,
+                                            uint32_t CE, uint32_t contCE,
+                                            uint32_t *nextCE, uint32_t *nextContCE,
+                                            uint32_t strength);
+U_CAPI int32_t U_EXPORT2 ucol_inv_getPrevCE(const UColTokenParser *src,
+                                            uint32_t CE, uint32_t contCE,
+                                            uint32_t *prevCE, uint32_t *prevContCE,
+                                            uint32_t strength);
 
 #endif /* #if !UCONFIG_NO_COLLATION */
 

Index: ucol_wgt.c
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucol_wgt.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ucol_wgt.c	10 Sep 2003 02:42:24 -0000	1.4
+++ ucol_wgt.c	6 Apr 2004 10:08:54 -0000	1.5
@@ -25,14 +25,12 @@
 #include "ucol_imp.h"
 #include "ucol_wgt.h"
 #include "cmemory.h"
+#include "uarrsort.h"
 
 #ifdef UCOL_DEBUG
 #   include <stdio.h>
 #endif
 
-/* we are using qsort() */
-#include <stdlib.h>
-
 #if defined(UCOL_DEBUG) && defined(WIN32)
     /* turn off "unreferenced formal parameter" */
 #   pragma warning(disable: 4100)
@@ -42,7 +40,7 @@
 
 /* helper functions for CE weights */
 
-static int32_t
+static U_INLINE int32_t
 lengthOfWeight(uint32_t weight) {
     if((weight&0xffffff)==0) {
         return 1;
@@ -55,23 +53,23 @@
     }
 }
 
-static uint32_t
+static U_INLINE uint32_t
 getWeightTrail(uint32_t weight, int32_t length) {
     return (uint32_t)(weight>>(8*(4-length)))&0xff;
 }
 
-static uint32_t
+static U_INLINE uint32_t
 setWeightTrail(uint32_t weight, int32_t length, uint32_t trail) {
     length=8*(4-length);
     return (uint32_t)((weight&(0xffffff00<<length))|(trail<<length));
 }
 
-static uint32_t
+static U_INLINE uint32_t
 getWeightByte(uint32_t weight, int32_t index) {
     return getWeightTrail(weight, index); /* same calculation */
 }
 
-static uint32_t
+static U_INLINE uint32_t
 setWeightByte(uint32_t weight, int32_t index, uint32_t byte) {
     uint32_t mask; /* 0xffffffff except a 00 "hole" for the index-th byte */
 
@@ -82,22 +80,22 @@
     return (uint32_t)((weight&mask)|(byte<<index));
 }
 
-static uint32_t
+static U_INLINE uint32_t
 truncateWeight(uint32_t weight, int32_t length) {
     return (uint32_t)(weight&(0xffffffff<<(8*(4-length))));
 }
 
-static uint32_t
+static U_INLINE uint32_t
 incWeightTrail(uint32_t weight, int32_t length) {
     return (uint32_t)(weight+(1UL<<(8*(4-length))));
 }
 
-static uint32_t
+static U_INLINE uint32_t
 decWeightTrail(uint32_t weight, int32_t length) {
     return (uint32_t)(weight-(1UL<<(8*(4-length))));
 }
 
-static uint32_t
+static U_INLINE uint32_t
 incWeight(uint32_t weight, int32_t length, uint32_t maxByte) {
     uint32_t byte;
 
@@ -113,7 +111,7 @@
     }
 }
 
-static int32_t
+static U_INLINE int32_t
 lengthenRange(WeightRange *range, uint32_t maxByte, uint32_t countBytes) {
     int32_t length;
 
@@ -125,9 +123,9 @@
     return length;
 }
 
-/* for qsort: sort ranges in weight order */
-static int
-compareRanges(const void *left, const void *right) {
+/* for uprv_sortArray: sort ranges in weight order */
+static U_INLINE int32_t U_CALLCONV
+compareRanges(const void *context, const void *left, const void *right) {
     uint32_t l, r;
 
     l=((const WeightRange *)left)->start;
@@ -146,7 +144,7 @@
  * possible ranges of weights between the two limits, excluding them
  * for weights with up to 4 bytes there are up to 2*4-1=7 ranges
  */
-static int32_t
+static U_INLINE int32_t
 getWeightRanges(uint32_t lowerLimit, uint32_t upperLimit,
                 uint32_t maxByte, uint32_t countBytes,
                 WeightRange ranges[7]) {
@@ -318,7 +316,7 @@
 
     uint32_t lengthCounts[6]; /* [0] unused, [5] to make index checks unnecessary */
     uint32_t maxCount;
-    int32_t i, rangeCount, minLength, maxLength;
+    int32_t i, rangeCount, minLength/*, maxLength*/;
 
     /* countBytes to the power of index */
     uint32_t powers[5];
@@ -391,8 +389,7 @@
             /* easy case, just make this one range large enough by lengthening it once more, possibly split it */
             uint32_t count1, count2, power_1, power;
 
-            rangeCount=1;
-            maxLength=minLength+1;
+            /*maxLength=minLength+1;*/
 
             /* calculate how to split the range between maxLength-1 (count1) and maxLength (count2) */
             power_1=powers[minLength-ranges[0].length];
@@ -405,6 +402,8 @@
             printf("split the first range %ld:%ld\n", count1, count2);
 #endif
             if(count1<1) {
+                rangeCount=1;
+
                 /* lengthen the entire range to maxLength */
                 lengthenRange(ranges, maxByte, countBytes);
             } else {
@@ -464,7 +463,9 @@
 
     if(rangeCount>1) {
         /* sort the ranges by weight values */
-        qsort(ranges, rangeCount, sizeof(WeightRange), compareRanges);
+        UErrorCode errorCode=U_ZERO_ERROR;
+        uprv_sortArray(ranges, rangeCount, sizeof(WeightRange), compareRanges, NULL, FALSE, &errorCode);
+        /* ignore error code: we know that the internal sort function will not fail here */
     }
 
 #ifdef UCOL_DEBUG

Index: ucoleitr.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucoleitr.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ucoleitr.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ ucoleitr.cpp	6 Apr 2004 10:08:54 -0000	1.5
@@ -243,6 +243,7 @@
       ci->flags |= UCOL_ITER_HASLEN;
   }
   ci->fcdPosition = NULL;
+  elems->reset_ = FALSE;
 }
 
 U_CAPI int32_t U_EXPORT2

Index: ucurr.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/ucurr.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ucurr.cpp	10 Sep 2003 02:42:24 -0000	1.1
+++ ucurr.cpp	6 Apr 2004 10:08:54 -0000	1.2
@@ -13,6 +13,8 @@
 #include "unicode/locid.h"
 #include "unicode/resbund.h"
 #include "unicode/ustring.h"
+#include "unicode/choicfmt.h"
+#include "ustr_imp.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "uassert.h"
@@ -57,6 +59,13 @@
 // Variant delimiter
 static const char VAR_DELIM[] = "_";
 
+// Variant for legacy euro mapping in CurrencyMap
+static const char VAR_DELIM_EURO[] = "_EURO";
+
+#define VARIANT_IS_EMPTY    0
+#define VARIANT_IS_EURO     0x1
+#define VARIANT_IS_PREEURO  0x2
+
 // Tag for localized display names (symbols) of currencies
 static const char CURRENCIES[] = "Currencies";
 
@@ -95,7 +104,7 @@
     UErrorCode ec = U_ZERO_ERROR;
     ResourceBundle currencyMeta =
         ResourceBundle((char*)0, Locale(""), ec).get(CURRENCY_META, ec);
-    
+
     if (U_FAILURE(ec)) {
         // Config/build error; return hard-coded defaults
         return LAST_RESORT_DATA;
@@ -141,7 +150,7 @@
     CReg *next;
     UChar iso[ISO_COUNTRY_CODE_LENGTH+1];
     char  id[ULOC_FULLNAME_CAPACITY];
-    
+
     CReg(const UChar* _iso, const char* _id)
         : next(0)
     {
@@ -154,7 +163,7 @@
         uprv_memcpy(iso, _iso, ISO_COUNTRY_CODE_LENGTH * sizeof(const UChar));
         iso[ISO_COUNTRY_CODE_LENGTH] = 0;
     }
-    
+
     static UCurrRegistryKey reg(const UChar* _iso, const char* _id, UErrorCode* status)
     {
         if (status && U_SUCCESS(*status) && _iso && _id) {
@@ -163,6 +172,7 @@
                 umtx_init(&gCRegLock);
                 Mutex mutex(&gCRegLock);
                 if (!gCRegHead) {
+                    /* register for the first time */
                     ucln_i18n_registerCleanup();
                 }
                 n->next = gCRegHead;
@@ -173,7 +183,7 @@
         }
         return 0;
     }
-    
+
     static UBool unreg(UCurrRegistryKey key) {
         umtx_init(&gCRegLock);
         Mutex mutex(&gCRegLock);
@@ -182,24 +192,26 @@
             delete (CReg*)key;
             return TRUE;
         }
-        
+
         CReg* p = gCRegHead;
         while (p) {
             if (p->next == key) {
                 p->next = ((CReg*)key)->next;
-                delete (CReg*)key;	
+                delete (CReg*)key;
                 return TRUE;
             }
             p = p->next;
         }
-        
+
         return FALSE;
     }
-    
+
     static const UChar* get(const char* id) {
         umtx_init(&gCRegLock);
         Mutex mutex(&gCRegLock);
         CReg* p = gCRegHead;
+
+        ucln_i18n_registerCleanup(); /* register cleanup of the mutex */
         while (p) {
             if (uprv_strcmp(id, p->id) == 0) {
                 return p->iso;
@@ -222,27 +234,36 @@
 
 // -------------------------------------
 
-static void
+/**
+ * @see VARIANT_IS_EURO
+ * @see VARIANT_IS_PREEURO
+ */
+static uint32_t
 idForLocale(const char* locale, char* buffer, int capacity, UErrorCode* ec)
 {
+    uint32_t variantType = 0;
     // !!! this is internal only, assumes buffer is not null and capacity is sufficient
     // Extract the country name and variant name.  We only
     // recognize two variant names, EURO and PREEURO.
     char variant[ULOC_FULLNAME_CAPACITY];
     uloc_getCountry(locale, buffer, capacity, ec);
     uloc_getVariant(locale, variant, sizeof(variant), ec);
-    if (0 == uprv_strcmp(variant, VAR_PRE_EURO) ||
-        0 == uprv_strcmp(variant, VAR_EURO))
-    {
-        uprv_strcat(buffer, VAR_DELIM);
-        uprv_strcat(buffer, variant);
+    if (variant[0] != 0) {
+        variantType = (0 == uprv_strcmp(variant, VAR_EURO))
+                   | ((0 == uprv_strcmp(variant, VAR_PRE_EURO)) << 1);
+        if (variantType)
+        {
+            uprv_strcat(buffer, VAR_DELIM);
+            uprv_strcat(buffer, variant);
+        }
     }
+    return variantType;
 }
 
 // -------------------------------------
 
 U_CAPI UCurrRegistryKey U_EXPORT2
-ucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status) 
+ucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status)
 {
     if (status && U_SUCCESS(*status)) {
         char id[ULOC_FULLNAME_CAPACITY];
@@ -255,7 +276,7 @@
 // -------------------------------------
 
 U_CAPI UBool U_EXPORT2
-ucurr_unregister(UCurrRegistryKey key, UErrorCode* status) 
+ucurr_unregister(UCurrRegistryKey key, UErrorCode* status)
 {
     if (status && U_SUCCESS(*status)) {
         return CReg::unreg(key);
@@ -265,33 +286,74 @@
 
 // -------------------------------------
 
-U_CAPI const UChar* U_EXPORT2
-ucurr_forLocale(const char* locale, UErrorCode* ec) {
+U_CAPI int32_t U_EXPORT2
+ucurr_forLocale(const char* locale,
+                UChar* buff,
+                int32_t buffCapacity,
+                UErrorCode* ec)
+{
+    int32_t resLen = 0;
+    const UChar* s = NULL;
     if (ec != NULL && U_SUCCESS(*ec)) {
-        char id[ULOC_FULLNAME_CAPACITY];
-        idForLocale(locale, id, sizeof(id), ec);
-        if (U_FAILURE(*ec)) {
-            return NULL;
-        }
-        
-        const UChar* result = CReg::get(id);
-        if (result) {
-            return result;
-        }
-        
-        // Look up the CurrencyMap element in the root bundle.
-        UResourceBundle* rb = ures_open(NULL, "", ec);
-        UResourceBundle* cm = ures_getByKey(rb, CURRENCY_MAP, NULL, ec);
-        int32_t len;
-        const UChar* s = ures_getStringByKey(cm, id, &len, ec);
-        ures_close(cm);
-        ures_close(rb);
-        
-        if (U_SUCCESS(*ec)) {
-            return s;
+        if ((buff && buffCapacity) || !buffCapacity) {
+            UErrorCode localStatus = U_ZERO_ERROR;
+            char id[ULOC_FULLNAME_CAPACITY];
+            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
+                // there is a currency keyword. Try to see if it's valid
+                if(buffCapacity > resLen) {
+                    u_charsToUChars(id, buff, resLen);
+                }
+            } else {
+                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
+
+                if (U_FAILURE(*ec)) {
+                    return 0;
+                }
+
+                const UChar* result = CReg::get(id);
+                if (result) {
+                    if(buffCapacity > u_strlen(result)) {
+                        u_strcpy(buff, result);
+                    }
+                    return u_strlen(result);
+                }
+
+                // Look up the CurrencyMap element in the root bundle.
+                UResourceBundle *rb = ures_open(NULL, "", &localStatus);
+                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
+                s = ures_getStringByKey(cm, id, &resLen, &localStatus);
+
+                if ((s == NULL || U_FAILURE(localStatus)) && variantType != VARIANT_IS_EMPTY
+                    && (id[0] != 0))
+                {
+                    // We don't know about it.  Check to see if we support the variant.
+                    if (variantType & VARIANT_IS_EURO) {
+                        s = ures_getStringByKey(cm, VAR_DELIM_EURO, &resLen, ec);
+                    }
+                    else {
+                        uloc_getParent(locale, id, sizeof(id), ec);
+                        *ec = U_USING_FALLBACK_WARNING;
+                        ures_close(cm);
+                        return ucurr_forLocale(id, buff, buffCapacity, ec);
+                    }
+                }
+                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
+                    // There is nothing to fallback to. Report the failure/warning if possible.
+                    *ec = localStatus;
+                }
+                if (U_SUCCESS(*ec)) {
+                    if(buffCapacity > resLen) {
+                        u_strcpy(buff, s);
+                    }
+                }
+                ures_close(cm);
+            }
+            return u_terminateUChars(buff, buffCapacity, resLen, ec);
+        } else {
+            *ec = U_ILLEGAL_ARGUMENT_ERROR;
         }
     }
-    return NULL;
+    return resLen;
 }
 
 // end registration
@@ -331,7 +393,7 @@
     // Look up the Currencies resource for the given locale.  The
     // Currencies locale data looks like this:
     //|en {
-    //|  Currencies { 
+    //|  Currencies {
     //|    USD { "US$", "US Dollar" }
     //|    CHF { "Sw F", "Swiss Franc" }
     //|    INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
@@ -348,7 +410,7 @@
         *ec = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
-    
+
     // In the future, resource bundles may implement multi-level
     // fallback.  That is, if a currency is not found in the en_US
     // Currencies data, then the en Currencies data will be searched.
@@ -414,23 +476,40 @@
     return currency;
 }
 
-//!// This API is now redundant.  It predates ucurr_getName, which
-//!// replaces and extends it.
-//!U_CAPI const UChar* U_EXPORT2
-//!ucurr_getSymbol(const UChar* currency,
-//!                const char* locale,
-//!    int32_t* len, // fillin
-//!                UErrorCode* ec) {
-//!    UBool isChoiceFormat;
-//!    const UChar* s = ucurr_getName(currency, locale, UCURR_SYMBOL_NAME,
-//!                                   &isChoiceFormat, len, ec);
-//!    if (isChoiceFormat) {
-//!        // Don't let ChoiceFormat patterns out through this API
-//!        *len = u_strlen(currency); // Should == 3, but maybe not...?
-//!        return currency;
-//!    }
-//!    return s;
-//!}
+/**
+ * Internal method.  Given a currency ISO code and a locale, return
+ * the "static" currency name.  This is usually the same as the
+ * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
+ * format is applied to the number 2.0 (to yield the more common
+ * plural) to return a static name.
+ *
+ * This is used for backward compatibility with old currency logic in
+ * DecimalFormat and DecimalFormatSymbols.
+ */
+U_CAPI void
+uprv_getStaticCurrencyName(const UChar* iso, const char* loc,
+                           UnicodeString& result, UErrorCode& ec)
+{
+    UBool isChoiceFormat;
+    int32_t len;
+    const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME,
+                                          &isChoiceFormat, &len, &ec);
+    if (U_SUCCESS(ec)) {
+        // If this is a ChoiceFormat currency, then format an
+        // arbitrary value; pick something != 1; more common.
+        result.truncate(0);
+        if (isChoiceFormat) {
+            ChoiceFormat f(currname, ec);
+            if (U_SUCCESS(ec)) {
+                f.format(2.0, result);
+            } else {
+                result = iso;
+            }
+        } else {
+            result = currname;
+        }
+    }
+}
 
 U_CAPI int32_t U_EXPORT2
 ucurr_getDefaultFractionDigits(const UChar* currency) {

Index: udat.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/udat.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- udat.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ udat.cpp	6 Apr 2004 10:08:54 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-*   Copyright (C) 1996-2001, International Business Machines
+*   Copyright (C) 1996-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *******************************************************************************
 */
@@ -573,4 +573,17 @@
   }
 }
 
+U_CAPI const char* U_EXPORT2
+udat_getLocaleByType(const UDateFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status)
+{
+    if (fmt == NULL) {
+        if (U_SUCCESS(*status)) {
+            *status = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        return NULL;
+    }
+    return ((Format*)fmt)->getLocaleID(type, *status);
+}
 #endif /* #if !UCONFIG_NO_FORMATTING */

Index: umsg.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/umsg.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- umsg.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ umsg.cpp	6 Apr 2004 10:08:54 -0000	1.5
@@ -412,6 +412,7 @@
         UChar *stringVal;
         double tDouble=0;
         int32_t tInt =0;
+        int64_t tInt64 = 0;
         UDate tempDate = 0;
         switch(argTypes[i]) {
         case Formattable::kDate:
@@ -428,6 +429,11 @@
             tInt = va_arg(ap, int32_t);
             args[i].setLong(tInt);
             break;
+
+        case Formattable::kInt64:
+            tInt64 = va_arg(ap, int64_t);
+            args[i].setInt64(tInt64);
+            break;
             
         case Formattable::kString:
             // For some reason, a temporary is needed
@@ -513,6 +519,7 @@
     double *aDouble;
     UChar *aString;
     int32_t* aInt;
+    int64_t* aInt64;
     UnicodeString temp;
     int len =0;
     // assign formattables to varargs
@@ -538,7 +545,6 @@
             break;
 
         case Formattable::kLong:
-            
             aInt = va_arg(ap, int32_t*);
             if(aInt){
                 *aInt = (int32_t) args[i].getLong();
@@ -547,6 +553,15 @@
             }
             break;
 
+        case Formattable::kInt64:
+            aInt64 = va_arg(ap, int64_t*);
+            if(aInt64){
+                *aInt64 = args[i].getInt64();
+            }else{
+                *status=U_ILLEGAL_ARGUMENT_ERROR;
+            }
+            break;
+
         case Formattable::kString:
             aString = va_arg(ap, UChar*);
             if(aString){
@@ -568,6 +583,20 @@
 
     // clean up
     delete [] args;
+}
+
+U_CAPI const char* U_EXPORT2
+umsg_getLocaleByType(const UMessageFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status)
+{
+    if (fmt == NULL) {
+        if (U_SUCCESS(*status)) {
+            *status = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        return NULL;
+    }
+    return ((Format*)fmt)->getLocaleID(type, *status);
 }
 
 #endif /* #if !UCONFIG_NO_FORMATTING */

Index: unesctrn.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unesctrn.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- unesctrn.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ unesctrn.cpp	6 Apr 2004 10:08:54 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -73,7 +73,7 @@
     END
 };
 
-const char UnescapeTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnescapeTransliterator)
 
 /**
  * Factory methods.  Ignore the context.

Index: unesctrn.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unesctrn.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- unesctrn.h	10 Sep 2003 02:42:24 -0000	1.3
+++ unesctrn.h	6 Apr 2004 10:08:54 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2001-2002, International Business Machines
+*   Copyright (c) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -82,14 +82,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -120,11 +120,6 @@
 
     static UChar* copySpec(const UChar* spec);
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: uni2name.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/uni2name.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- uni2name.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ uni2name.cpp	6 Apr 2004 10:08:54 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -21,9 +21,9 @@
 
 U_NAMESPACE_BEGIN
 
-const char UnicodeNameTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeNameTransliterator)
 
-const char UnicodeNameTransliterator::_ID[] = "Any-Name";
+const char CURR_ID[] = "Any-Name";
 
 static const UChar OPEN_DELIM[] = {92,78,123,0}; // "\N{"
 static const UChar CLOSE_DELIM  = 125; // "}"
@@ -33,7 +33,7 @@
  * Constructs a transliterator.
  */
 UnicodeNameTransliterator::UnicodeNameTransliterator(UnicodeFilter* adoptedFilter) :
-    Transliterator(_ID, adoptedFilter) {
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter) {
 }
 
 /**

Index: uni2name.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/uni2name.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- uni2name.h	10 Sep 2003 02:42:24 -0000	1.3
+++ uni2name.h	6 Apr 2004 10:08:54 -0000	1.4
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2001, International Business Machines
+*   Copyright (C) 2001-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -58,14 +58,14 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
+    static UClassID getStaticClassID();
 
  protected:
 
@@ -81,15 +81,6 @@
     virtual void handleTransliterate(Replaceable& text, UTransPosition& offset,
                                      UBool isIncremental) const;
 
- private:
-
-    static const char _ID[];
-
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
 };
 
 U_NAMESPACE_END

Index: unifltlg.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unifltlg.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- unifltlg.cpp	10 Sep 2003 02:42:24 -0000	1.4
+++ unifltlg.cpp	6 Apr 2004 10:08:54 -0000	1.5
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1999-2001, International Business Machines
+*   Copyright (C) 1999-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -18,7 +18,7 @@
 
 #include "unicode/utypes.h"
 
-#if !UCONFIG_NO_TRANSLITERATION
+#if !UCONFIG_NO_TRANSLITERATION && defined(U_USE_UNICODE_FILTER_LOGIC_OBSOLETE_2_8)
 
 #include "unicode/unifltlg.h"
 #include "unicode/unifilt.h"

Index: unitohex.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unitohex.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- unitohex.cpp	10 Sep 2003 02:42:24 -0000	1.3
+++ unitohex.cpp	6 Apr 2004 10:08:54 -0000	1.4
@@ -18,14 +18,14 @@
 
 U_NAMESPACE_BEGIN
 
-const char UnicodeToHexTransliterator::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeToHexTransliterator)
 
 /**
  * ID for this transliterator.
  */
-const char UnicodeToHexTransliterator::_ID[] = "Any-Hex";
+const char CURR_ID[] = "Any-Hex";
 
-const UChar UnicodeToHexTransliterator::HEX_DIGITS[32] = {
+static const UChar HEX_DIGITS[32] = {
     // Use Unicode hex values for EBCDIC compatibility
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 01234567
     0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 89abcdef
@@ -33,6 +33,8 @@
     0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 89ABCDEF
 };
 
+UnicodeToHexTransliterator::~UnicodeToHexTransliterator() {}
+
 /**
  * Constructs a transliterator.
  */
@@ -41,8 +43,9 @@
                                 UBool isUppercase,
                                 UnicodeFilter* adoptedFilter,
                                 UErrorCode& status) :
-    Transliterator(_ID, adoptedFilter),
-    uppercase(isUppercase) {
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter),
+    uppercase(isUppercase)
+{
 
     if (U_FAILURE(status)) {
         return;
@@ -56,7 +59,7 @@
 UnicodeToHexTransliterator::UnicodeToHexTransliterator(
                                 const UnicodeString& thePattern,
                                 UErrorCode& status) :
-    Transliterator(_ID, 0),
+    Transliterator(UnicodeString(CURR_ID, ""), 0),
     uppercase(TRUE) {
 
     if (U_FAILURE(status)) {
@@ -71,7 +74,7 @@
  */
 UnicodeToHexTransliterator::UnicodeToHexTransliterator(
                                 UnicodeFilter* adoptedFilter) :
-    Transliterator(_ID, adoptedFilter),
+    Transliterator(UnicodeString(CURR_ID, ""), adoptedFilter),
     pattern("\\\\u0000", ""),
     prefix("\\u", 2, ""),
     suffix(),

Index: unitohex.h
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unitohex.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- unitohex.h	10 Sep 2003 02:42:24 -0000	1.1
+++ unitohex.h	6 Apr 2004 10:08:54 -0000	1.2
@@ -52,13 +52,6 @@
         BACKSLASH = 0x005C  // '\\'
     };
 
-    static const UChar HEX_DIGITS[32];
-
-    /**
-     * ID for this transliterator.
-     */
-    static const char _ID[];
-
     /**
      * The pattern set by applyPattern() and returned by toPattern().
      */
@@ -86,12 +79,6 @@
      */
     UBool uppercase;
 
-    /**
-     * The address of this static class variable serves as this class's ID
-     * for ICU "poor man's RTTI".
-     */
-    static const char fgClassID;
-
 public:
 
     /**
@@ -212,25 +199,15 @@
      *
      * @draft ICU 2.2
      */
-    virtual inline UClassID getDynamicClassID() const;
+    virtual UClassID getDynamicClassID() const;
 
     /**
      * ICU "poor man's RTTI", returns a UClassID for this class.
      *
      * @draft ICU 2.2
      */
-    static inline UClassID getStaticClassID();
+    static UClassID getStaticClassID();
 };
-
-inline UnicodeToHexTransliterator::~UnicodeToHexTransliterator() {}
-
-inline UClassID
-UnicodeToHexTransliterator::getStaticClassID()
-{ return (UClassID)&fgClassID; }
-
-inline UClassID
-UnicodeToHexTransliterator::getDynamicClassID() const
-{ return UnicodeToHexTransliterator::getStaticClassID(); }
 
 U_NAMESPACE_END
 #endif /* #if !UCONFIG_NO_TRANSLITERATION */

Index: unum.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/unum.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- unum.cpp	10 Sep 2003 02:42:24 -0000	1.8
+++ unum.cpp	6 Apr 2004 10:08:54 -0000	1.9
@@ -24,71 +24,9 @@
 #include "unicode/fmtable.h"
 #include "unicode/dcfmtsym.h"
 #include "cpputils.h"
-U_NAMESPACE_USE
-/*
-U_CAPI UNumberFormat*
-unum_open(    UNumberFormatStyle    style,
-        const   char*        locale,
-        UErrorCode*        status)
-{
-  if(U_FAILURE(*status))
[...1106 lines suppressed...]
-  
-  if(localized)
-    ((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
-  else
-    ((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
+U_CAPI const char* U_EXPORT2
+unum_getLocaleByType(const UNumberFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status)
+{
+    if (fmt == NULL) {
+        if (U_SUCCESS(*status)) {
+            *status = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        return NULL;
+    }
+    return ((Format*)fmt)->getLocaleID(type, *status);
 }
 
 #endif /* #if !UCONFIG_NO_FORMATTING */

Index: usearch.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/usearch.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- usearch.cpp	10 Sep 2003 02:42:24 -0000	1.5
+++ usearch.cpp	6 Apr 2004 10:08:55 -0000	1.6
@@ -39,13 +39,13 @@
 inline void setColEIterOffset(UCollationElements *elems,
                       int32_t             offset)
 {
-	collIterate *ci = &(elems->iteratordata_);
-	ci->pos         = ci->string + offset;
-	ci->CEpos       = ci->toReturn = ci->CEs;
-	if (ci->flags & UCOL_ITER_INNORMBUF) {
-		ci->flags = ci->origFlags;
-	}
-	ci->fcdPosition = NULL;
+    collIterate *ci = &(elems->iteratordata_);
+    ci->pos         = ci->string + offset;
+    ci->CEpos       = ci->toReturn = ci->CEs;
+    if (ci->flags & UCOL_ITER_INNORMBUF) {
+        ci->flags = ci->origFlags;
+    }
+    ci->fcdPosition = NULL;
 }
 
 /**
@@ -404,7 +404,7 @@
         int32_t   cesize  = pattern->CELength;
 
         int16_t minlength = cesize > expandlength 
-			                ? (int16_t)cesize - expandlength : 1;
+                            ? (int16_t)cesize - expandlength : 1;
         pattern->defaultShiftSize    = minlength;
         setShiftTable(pattern->shift, pattern->backShift, pattern->CE,
                       cesize, expandlength, minlength, minlength);
@@ -522,7 +522,7 @@
 inline int32_t getNextUStringSearchBaseOffset(UStringSearch *strsrch, 
                                                   int32_t    textoffset)
 {
-	int32_t textlength = strsrch->search->textLength;
+    int32_t textlength = strsrch->search->textLength;
     if (strsrch->pattern.hasSuffixAccents && 
         textoffset < textlength) {
               int32_t  temp       = textoffset;
@@ -553,7 +553,7 @@
                                 uint32_t       ce,
                                 int32_t        patternceindex)
 {
-	UPattern *pattern = &(strsrch->pattern);
+    UPattern *pattern = &(strsrch->pattern);
     if (ce != UCOL_NULLORDER) {
         int32_t shift = pattern->shift[hash(ce)];
         // this is to adjust for characters in the middle of the 
@@ -745,9 +745,9 @@
         uint32_t            ignorable = TRUE;
         uint32_t            firstce   = strsrch->pattern.CE[0];
 
-		setColEIterOffset(coleiter, start);
+        setColEIterOffset(coleiter, start);
         uint32_t ce  = getCE(strsrch, ucol_next(coleiter, &status));
-		if (U_FAILURE(status)) {
+        if (U_FAILURE(status)) {
             return TRUE;
         }
         while (ce != firstce) {
@@ -759,26 +759,26 @@
                 return TRUE;
             }
         }
-		if (!ignorable && inNormBuf(coleiter)) {
+        if (!ignorable && inNormBuf(coleiter)) {
             // within normalization buffer, discontiguous handled here
-		    return TRUE;
+            return TRUE;
         }
 
-		// within text
+        // within text
         int32_t temp = start;
-		// original code
-		// accent = (getFCD(strsrch->search->text, &temp, 
+        // original code
+        // accent = (getFCD(strsrch->search->text, &temp, 
         //                  strsrch->search->textLength) 
-		//   	     >> SECOND_LAST_BYTE_SHIFT_); 
-		// however this code does not work well with VC7 .net in release mode.
-		// maybe the inlines for getFCD combined with shifting has bugs in 
-		// VC7. anyways this is a work around.
-		UBool accent = getFCD(strsrch->search->text, &temp, 
+        //            >> SECOND_LAST_BYTE_SHIFT_); 
+        // however this code does not work well with VC7 .net in release mode.
+        // maybe the inlines for getFCD combined with shifting has bugs in 
+        // VC7. anyways this is a work around.
+        UBool accent = getFCD(strsrch->search->text, &temp, 
                               strsrch->search->textLength) > 0xFF;
         if (!accent) {
-			return checkExtraMatchAccents(strsrch, start, end, &status);
+            return checkExtraMatchAccents(strsrch, start, end, &status);
         }
-		if (!ignorable) {
+        if (!ignorable) {
             return TRUE;
         }
         if (start > 0) {
@@ -937,7 +937,7 @@
     else {
         result = start >= lastmatchindex;
     }
-    if (!strsrch->search->isOverlap) {
+    if (!result && !strsrch->search->isOverlap) {
         if (strsrch->search->isForwardSearching) {
             result = start < lastmatchindex + strsrch->search->matchedLength;
         }
@@ -993,13 +993,13 @@
     const UChar              *text       = strsrch->search->text;
     // This part checks if either ends of the match contains potential 
     // contraction. If so we'll have to iterate through them
-	// The start contraction needs to be checked since ucol_previous dumps
-	// all characters till the first safe character into the buffer.
-	// *start + 1 is used to test for the unsafe characters instead of *start 
-	// because ucol_prev takes all unsafe characters till the first safe 
-	// character ie *start. so by testing *start + 1, we can estimate if 
-	// excess prefix characters has been included in the potential search 
-	// results.
+    // The start contraction needs to be checked since ucol_previous dumps
+    // all characters till the first safe character into the buffer.
+    // *start + 1 is used to test for the unsafe characters instead of *start 
+    // because ucol_prev takes all unsafe characters till the first safe 
+    // character ie *start. so by testing *start + 1, we can estimate if 
+    // excess prefix characters has been included in the potential search 
+    // results.
     if ((*end < textlength && ucol_unsafeCP(text[*end], collator)) || 
         (*start + 1 < textlength 
          && ucol_unsafeCP(text[*start + 1], collator))) {
@@ -1015,9 +1015,9 @@
             // we are only looking for acute and ring \u030A and \u0301, we'll
             // have to skip the first ce in the expansion buffer.
             ucol_next(coleiter, status);
-			if (U_FAILURE(*status)) {
-				return FALSE;
-			}
+            if (U_FAILURE(*status)) {
+                return FALSE;
+            }
             if (ucol_getOffset(coleiter) != temp) {
                 *start = temp;
                 temp  = ucol_getOffset(coleiter);
@@ -1075,8 +1075,8 @@
     UCollationElements *coleiter = strsrch->textIter;
     int32_t         start    = getColElemIterOffset(coleiter, FALSE);        
         
-	if (!checkNextExactContractionMatch(strsrch, &start, textoffset, status)) {
-	    return FALSE;
+    if (!checkNextExactContractionMatch(strsrch, &start, textoffset, status)) {
+        return FALSE;
     }
 
     // this totally matches, however we need to check if it is repeating
@@ -1085,16 +1085,16 @@
         hasAccentsBeforeMatch(strsrch, start, *textoffset) || 
         !checkIdentical(strsrch, start, *textoffset) ||
         hasAccentsAfterMatch(strsrch, start, *textoffset)) {
-		
-		(*textoffset) ++;
+
+        (*textoffset) ++;
         *textoffset = getNextUStringSearchBaseOffset(strsrch, *textoffset);  
-		return FALSE;
+        return FALSE;
     }
         
     // totally match, we will get rid of the ending ignorables.
     strsrch->search->matchedIndex  = start;
     strsrch->search->matchedLength = *textoffset - start;
-	return TRUE;
+    return TRUE;
 }
 
 /**
@@ -1288,7 +1288,7 @@
     int32_t         accentsindex[INITIAL_ARRAY_SIZE_];      
     int32_t         accentsize = getUnblockedAccentIndex(accents, 
                                                                  accentsindex);
-    int32_t         count      = (2 << (accentsize - 1)) - 2;  
+    int32_t         count      = (2 << (accentsize - 1)) - 1; 
     UChar               buffer[INITIAL_ARRAY_SIZE_];
     UCollationElements *coleiter   = strsrch->utilIter;
     while (U_SUCCESS(*status) && count > 0) {
@@ -1560,8 +1560,8 @@
     int32_t accentsindex[INITIAL_ARRAY_SIZE_];
     int32_t size = getUnblockedAccentIndex(accents, accentsindex);
 
-    // 2 power n - 1 minus the full set of accents
-    int32_t  count = (2 << (size - 1)) - 2;  
+    // 2 power n - 1 plus the full set of accents
+    int32_t  count = (2 << (size - 1)) - 1;
     while (U_SUCCESS(*status) && count > 0) {
         UChar *rearrange = strsrch->canonicalSuffixAccents;
         // copy the base characters
@@ -1638,7 +1638,7 @@
     const UChar              *text       = strsrch->search->text;
     // This part checks if either ends of the match contains potential 
     // contraction. If so we'll have to iterate through them
-	if ((*end < textlength && ucol_unsafeCP(text[*end], collator)) || 
+    if ((*end < textlength && ucol_unsafeCP(text[*end], collator)) || 
         (*start + 1 < textlength 
          && ucol_unsafeCP(text[*start + 1], collator))) {
         int32_t expansion  = getExpansionPrefix(coleiter);
@@ -1653,9 +1653,9 @@
             // we are only looking for acute and ring \u030A and \u0301, we'll
             // have to skip the first ce in the expansion buffer.
             ucol_next(coleiter, status);
-			if (U_FAILURE(*status)) {
-				return FALSE;
-			}
+            if (U_FAILURE(*status)) {
+                return FALSE;
+            }
             if (ucol_getOffset(coleiter) != temp) {
                 *start = temp;
                 temp  = ucol_getOffset(coleiter);
@@ -1835,9 +1835,9 @@
     const UChar              *text       = strsrch->search->text;
     // This part checks if either if the start of the match contains potential 
     // contraction. If so we'll have to iterate through them
-	// Since we used ucol_next while previously looking for the potential 
-	// match, this guarantees that our end will not be a partial contraction,
-	// or a partial supplementary character.
+    // Since we used ucol_next while previously looking for the potential 
+    // match, this guarantees that our end will not be a partial contraction,
+    // or a partial supplementary character.
     if (*start < textlength && ucol_unsafeCP(text[*start], collator)) {
         int32_t expansion  = getExpansionSuffix(coleiter);
         UBool   expandflag = expansion > 0;
@@ -1851,9 +1851,9 @@
             // we are only looking for A ring A\u030A, we'll have to skip the 
             // last ce in the expansion buffer
             ucol_previous(coleiter, status);
-			if (U_FAILURE(*status)) {
-				return FALSE;
-			}
+            if (U_FAILURE(*status)) {
+                return FALSE;
+            }
             if (ucol_getOffset(coleiter) != temp) {
                 *end = temp;
                 temp  = ucol_getOffset(coleiter);
@@ -1984,7 +1984,7 @@
         int32_t         accentsindex[INITIAL_ARRAY_SIZE_];      
         int32_t         accentsize = getUnblockedAccentIndex(accents, 
                                                          accentsindex);
-        int32_t         count      = (2 << (accentsize - 1)) - 2;  
+        int32_t         count      = (2 << (accentsize - 1)) - 1;  
         UChar               buffer[INITIAL_ARRAY_SIZE_];
         UCollationElements *coleiter = strsrch->utilIter;
         while (U_SUCCESS(*status) && count > 0) {
@@ -2217,8 +2217,8 @@
     int32_t accentsindex[INITIAL_ARRAY_SIZE_];
     int32_t size = getUnblockedAccentIndex(accents, accentsindex);
 
-    // 2 power n - 1 minus the full set of accents
-    int32_t  count = (2 << (size - 1)) - 2;  
+    // 2 power n - 1 plus the full set of accents
+    int32_t  count = (2 << (size - 1)) - 1;  
     while (U_SUCCESS(*status) && count > 0) {
         UChar *rearrange = strsrch->canonicalPrefixAccents;
         // copy the base characters
@@ -2267,11 +2267,11 @@
           int32_t         temp       = *end;
     const UCollator          *collator   = strsrch->collator;
     const UChar              *text       = strsrch->search->text;
-	// This part checks if either if the start of the match contains potential 
+    // This part checks if either if the start of the match contains potential 
     // contraction. If so we'll have to iterate through them
-	// Since we used ucol_next while previously looking for the potential 
-	// match, this guarantees that our end will not be a partial contraction,
-	// or a partial supplementary character.
+    // Since we used ucol_next while previously looking for the potential 
+    // match, this guarantees that our end will not be a partial contraction,
+    // or a partial supplementary character.
     if (*start < textlength && ucol_unsafeCP(text[*start], collator)) {
         int32_t expansion  = getExpansionSuffix(coleiter);
         UBool   expandflag = expansion > 0;
@@ -2285,9 +2285,9 @@
             // we are only looking for A ring A\u030A, we'll have to skip the 
             // last ce in the expansion buffer
             ucol_previous(coleiter, status);
-			if (U_FAILURE(*status)) {
-				return FALSE;
-			}
+            if (U_FAILURE(*status)) {
+                return FALSE;
+            }
             if (ucol_getOffset(coleiter) != temp) {
                 *end = temp;
                 temp  = ucol_getOffset(coleiter);
@@ -2739,10 +2739,10 @@
             strsrch->search->matchedLength = 0;
             strsrch->search->reset         = TRUE;
 #if !UCONFIG_NO_BREAK_ITERATION
-			if (strsrch->search->breakIter != NULL) {
-				ubrk_setText(strsrch->search->breakIter, text, 
-							 textlength, status);
-			}
+            if (strsrch->search->breakIter != NULL) {
+                ubrk_setText(strsrch->search->breakIter, text, 
+                             textlength, status);
+            }
 #endif
         }
     }
@@ -2787,7 +2787,7 @@
                     uprv_init_collIterate(collator, strsrch->search->text, 
                                           strsrch->search->textLength, 
                                           &(strsrch->textIter->iteratordata_));
-					strsrch->utilIter->iteratordata_.coll = collator;
+                    strsrch->utilIter->iteratordata_.coll = collator;
                 }
             }
         }
@@ -2921,17 +2921,18 @@
                                           UErrorCode    *status)
 { 
     if (U_SUCCESS(*status) && strsrch) {
-        int32_t  offset     = usearch_getOffset(strsrch);
-        USearch     *search     = strsrch->search;
-        search->reset           = FALSE;
-        int32_t      textlength = search->textLength;
-        int32_t  matchedindex = search->matchedIndex;
+        // note offset is either equivalent to the start of the previous match
+        // or is set by the user
+        int32_t      offset       = usearch_getOffset(strsrch);
+        USearch     *search       = strsrch->search;
+        search->reset             = FALSE;
+        int32_t      textlength   = search->textLength;
         if (search->isForwardSearching) {
-            if (offset == textlength || matchedindex == textlength || 
-                (!search->isOverlap && 
+            if (offset == textlength
+                || (!search->isOverlap && 
                     (offset + strsrch->pattern.defaultShiftSize > textlength ||
-                    (matchedindex != USEARCH_DONE && 
-                    matchedindex + search->matchedLength >= textlength)))) {
+                    (search->matchedIndex != USEARCH_DONE && 
+                     offset + search->matchedLength >= textlength)))) {
                 // not enough characters to match
                 setMatchNotFound(strsrch);
                 return USEARCH_DONE; 
@@ -2944,16 +2945,16 @@
             // string. the iterator would have been set to offset 0 if a 
             // match is not found.
             search->isForwardSearching = TRUE;
-            if (matchedindex != USEARCH_DONE) {
+            if (search->matchedIndex != USEARCH_DONE) {
                 // there's no need to set the collation element iterator
                 // the next call to next will set the offset.
-                return matchedindex;
+                return search->matchedIndex;
             }
         }
 
         if (U_SUCCESS(*status)) {
             if (strsrch->pattern.CELength == 0) {
-                if (matchedindex == USEARCH_DONE) {
+                if (search->matchedIndex == USEARCH_DONE) {
                     search->matchedIndex = offset;
                 }
                 else { // moves by codepoints
@@ -2968,30 +2969,37 @@
                 }
             }
             else {
-				if (search->matchedLength > 0) {
-					// if matchlength is 0 we are at the start of the iteration
-					int offset = ucol_getOffset(strsrch->textIter);
-					if (search->isOverlap) {
-						ucol_setOffset(strsrch->textIter, offset + 1, status);
-					}
-					else {
-						ucol_setOffset(strsrch->textIter, 
-							           offset + search->matchedLength, status);
-					}
-				}
-				if (search->isCanonicalMatch) {
-					// can't use exact here since extra accents are allowed.
-					usearch_handleNextCanonical(strsrch, status);
-				}
-				else {
-					usearch_handleNextExact(strsrch, status);
-				}
-			}
-            
+                if (search->matchedLength > 0) {
+                    // if matchlength is 0 we are at the start of the iteration
+                    if (search->isOverlap) {
+                        ucol_setOffset(strsrch->textIter, offset + 1, status);
+                    }
+                    else {
+                        ucol_setOffset(strsrch->textIter, 
+                                       offset + search->matchedLength, status);
+                    }
+                }
+                else {
+                    // for boundary check purposes. this will ensure that the
+                    // next match will not preceed the current offset
+                    // note search->matchedIndex will always be set to something
+                    // in the code
+                    search->matchedIndex = offset - 1;
+                }
+
+                if (search->isCanonicalMatch) {
+                    // can't use exact here since extra accents are allowed.
+                    usearch_handleNextCanonical(strsrch, status);
+                }
+                else {
+                    usearch_handleNextExact(strsrch, status);
+                }
+            }
+
             if (U_FAILURE(*status)) {
                 return USEARCH_DONE;
             }
-            
+
             return search->matchedIndex;
         }
     }
@@ -3135,15 +3143,15 @@
         return FALSE;
     }
 
-	UCollationElements *coleiter        = strsrch->textIter;
+    UCollationElements *coleiter        = strsrch->textIter;
     int32_t             textlength      = strsrch->search->textLength;
     uint32_t           *patternce       = strsrch->pattern.CE;
     int32_t             patterncelength = strsrch->pattern.CELength;
     int32_t             textoffset      = ucol_getOffset(coleiter);
 
-	// status used in setting coleiter offset, since offset is checked in
-	// shiftForward before setting the coleiter offset, status never 
-	// a failure
+    // status used in setting coleiter offset, since offset is checked in
+    // shiftForward before setting the coleiter offset, status never 
+    // a failure
     textoffset = shiftForward(strsrch, textoffset, UCOL_NULLORDER, 
                               patterncelength);
     while (textoffset <= textlength)
@@ -3152,9 +3160,9 @@
         uint32_t    targetce;
         UBool       found          = FALSE;
         uint32_t    lastce         = UCOL_NULLORDER;
-        
-		setColEIterOffset(coleiter, textoffset);
-    
+
+        setColEIterOffset(coleiter, textoffset);
+
         while (TRUE) {
             // finding the last pattern ce match, imagine composite characters
             // for example: search for pattern A in text \u00C0
@@ -3202,24 +3210,24 @@
         }
 
         if (!found) {
-			if (U_FAILURE(*status)) {
-				break;
-			}
-            textoffset = shiftForward(strsrch, textoffset, targetce, 
+            if (U_FAILURE(*status)) {
+                break;
+            }
+            textoffset = shiftForward(strsrch, textoffset, lastce, 
                                       patternceindex);
             // status checked at loop.
             patternceindex = patterncelength;
             continue;
         }
-        
-		if (checkNextExactMatch(strsrch, &textoffset, status)) {
+
+        if (checkNextExactMatch(strsrch, &textoffset, status)) {
             // status checked in ucol_setOffset
-            setColEIterOffset(coleiter,	strsrch->search->matchedIndex);
-			return TRUE;
+            setColEIterOffset(coleiter, strsrch->search->matchedIndex);
+            return TRUE;
         }
     }
     setMatchNotFound(strsrch);
-	return FALSE;
+    return FALSE;
 }
 
 UBool usearch_handleNextCanonical(UStringSearch *strsrch, UErrorCode *status)
@@ -3233,7 +3241,7 @@
     int32_t             textlength      = strsrch->search->textLength;
     uint32_t           *patternce       = strsrch->pattern.CE;
     int32_t             patterncelength = strsrch->pattern.CELength;
-    int32_t         textoffset      = ucol_getOffset(coleiter);
+    int32_t             textoffset      = ucol_getOffset(coleiter);
     UBool               hasPatternAccents = 
        strsrch->pattern.hasSuffixAccents || strsrch->pattern.hasPrefixAccents;
     
@@ -3248,10 +3256,10 @@
         uint32_t    targetce;
         UBool       found          = FALSE;
         uint32_t    lastce         = UCOL_NULLORDER;
-        
-		setColEIterOffset(coleiter, textoffset);
-    
-        while (TRUE) {
+
+        setColEIterOffset(coleiter, textoffset);
+
+        for (;;) {
             // finding the last pattern ce match, imagine composite characters
             // for example: search for pattern A in text \u00C0
             // we'll have to skip \u0300 the grave first before we get to A
@@ -3274,7 +3282,6 @@
                 break;
             }
         }
-        targetce = lastce;
         
         while (found && patternceindex > 0) {
             targetce    = ucol_previous(coleiter, status);
@@ -3295,17 +3302,17 @@
         if (hasPatternAccents && !found) {
             strsrch->canonicalPrefixAccents[0] = 0;
             strsrch->canonicalSuffixAccents[0] = 0;
-			if (U_FAILURE(*status)) {
-				break;
-			}
+            if (U_FAILURE(*status)) {
+                break;
+            }
             found = doNextCanonicalMatch(strsrch, textoffset, status);
         }
 
         if (!found) {
-			if (U_FAILURE(*status)) {
-				break;
-			}
-            textoffset = shiftForward(strsrch, textoffset, targetce, 
+            if (U_FAILURE(*status)) {
+                break;
+            }
+            textoffset = shiftForward(strsrch, textoffset, lastce, 
                                       patternceindex);
             // status checked at loop
             patternceindex = patterncelength;
@@ -3350,10 +3357,10 @@
         UBool       found          = FALSE;
         uint32_t    firstce        = UCOL_NULLORDER;
 
-		// if status is a failure, ucol_setOffset does nothing
+        // if status is a failure, ucol_setOffset does nothing
         setColEIterOffset(coleiter, textoffset);
-        
-        while (TRUE) {
+
+        for (;;) {
             // finding the first pattern ce match, imagine composite 
             // characters. for example: search for pattern \u0300 in text 
             // \u00C0, we'll have to skip A first before we get to 
@@ -3399,9 +3406,9 @@
         }
 
         if (!found) {
-			if (U_FAILURE(*status)) {
-				break;
-			}
+            if (U_FAILURE(*status)) {
+                break;
+            }
             textoffset = reverseShift(strsrch, textoffset, targetce, 
                                       patternceindex);
             patternceindex = 0;
@@ -3500,14 +3507,14 @@
         if (hasPatternAccents && !found) {
             strsrch->canonicalPrefixAccents[0] = 0;
             strsrch->canonicalSuffixAccents[0] = 0;
-			if (U_FAILURE(*status)) {
+            if (U_FAILURE(*status)) {
                 break;
             }
             found = doPreviousCanonicalMatch(strsrch, textoffset, status);
         }
 
         if (!found) {
-			if (U_FAILURE(*status)) {
+            if (U_FAILURE(*status)) {
                 break;
             }
             textoffset = reverseShift(strsrch, textoffset, targetce, 

Index: utrans.cpp
===================================================================
RCS file: /cvs/core/icu-sword/source/i18n/utrans.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- utrans.cpp	10 Sep 2003 02:42:25 -0000	1.4
+++ utrans.cpp	6 Apr 2004 10:08:56 -0000	1.5
@@ -19,6 +19,8 @@
 #include "unicode/unifilt.h"
 #include "unicode/uniset.h"
 #include "unicode/ustring.h"
+#include "unicode/uenum.h"
+#include "uenumimp.h"
 #include "cpputils.h"
 #include "rbt.h"
 
@@ -132,84 +134,18 @@
  * General API
  ********************************************************************/
 U_NAMESPACE_USE
-#if 0
-
-U_CAPI UTransliterator*
-utrans_open(const char* id,
-            UTransDirection dir,
-            UParseError* parseError,
-            UErrorCode* status) {
-
-    utrans_ENTRY(status) NULL;
-
-    if (id == NULL) {
-        *status = U_ILLEGAL_ARGUMENT_ERROR;
-        return NULL;
-    }
-
-    UnicodeString ID(id, ""); // use invariant converter
-    Transliterator *trans = NULL;
-
-    trans = Transliterator::createInstance(ID, dir, *parseError, *status);
-
-    if (trans == NULL) {
-        *status = U_ILLEGAL_ARGUMENT_ERROR;
-    }
-    return (UTransliterator*) trans;
-}
 
-U_CAPI UTransliterator*
-utrans_openRules(const char* id,
-                 const UChar* rules,
-                 int32_t rulesLength, /* -1 if null-terminated */
-                 UTransDirection dir,
-                 UParseError* parseErr, /* may be NULL */
-                 UErrorCode* status) {
-
-    utrans_ENTRY(status) NULL;
-
-    if (id == NULL || rules == NULL) {
-        *status = U_ILLEGAL_ARGUMENT_ERROR;
+U_CAPI UTransliterator* U_EXPORT2
+utrans_openU(const UChar *id,
+             int32_t idLength,
+             UTransDirection dir,
+             const UChar *rules,
+             int32_t rulesLength,
+             UParseError *parseError,
+             UErrorCode *status) {
+    if(status==NULL || U_FAILURE(*status)) {
         return NULL;
     }
-
-    UnicodeString ID(id, ""); // use invariant converter
-    UnicodeString ruleStr(rulesLength < 0,
-                          rules,
-                          rulesLength); // r-o alias
-
-    RuleBasedTransliterator *trans = NULL;
-
-    // Use if() to avoid construction of ParseError object on stack
-    // unless it is called for by user.
-    if (parseErr != NULL) {
-        trans = new RuleBasedTransliterator(ID, ruleStr, dir,
-                                            NULL, *parseErr, *status);
-    } else {
-        trans = new RuleBasedTransliterator(ID, ruleStr, dir,
-                                            NULL, *status);
-    }
-
-    if (trans == NULL) {
-        *status = U_MEMORY_ALLOCATION_ERROR;
-    } else if (U_FAILURE(*status)) {
-        delete trans;
-        trans = NULL;
-    }
-    return (UTransliterator*) trans;
-}
-#endif
-
-U_CAPI UTransliterator* U_EXPORT2
-utrans_open(const char* id,
-            UTransDirection dir,
-            const UChar* rules,         /* may be Null */
-            int32_t rulesLength,        /* -1 if null-terminated */ 
-            UParseError* parseError,    /* may be Null */
-            UErrorCode* status) {
-
-    utrans_ENTRY(status) NULL;
-
     if (id == NULL) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return NULL;
@@ -220,7 +156,7 @@
         parseError = &temp;
     }
     
-    UnicodeString ID(id, ""); // use invariant converter
+    UnicodeString ID(idLength<0, id, idLength); // r-o alias
 
     if(rules==NULL){
 
@@ -251,6 +187,19 @@
 }
 
 U_CAPI UTransliterator* U_EXPORT2
+utrans_open(const char* id,
+            UTransDirection dir,
+            const UChar* rules,         /* may be Null */
+            int32_t rulesLength,        /* -1 if null-terminated */ 
+            UParseError* parseError,    /* may be Null */
+            UErrorCode* status) {
+    UnicodeString ID(id, ""); // use invariant converter
+    return utrans_openU(ID.getBuffer(), ID.length(), dir,
+                        rules, rulesLength,
+                        parseError, status);
+}
+
+U_CAPI UTransliterator* U_EXPORT2
 utrans_openInverse(const UTransliterator* trans,
                    UErrorCode* status) {
 
@@ -285,6 +234,17 @@
     delete (Transliterator*) trans;
 }
 
+U_CAPI const UChar * U_EXPORT2
+utrans_getUnicodeID(const UTransliterator *trans,
+                    int32_t *resultLength) {
+    // Transliterator keeps its ID NUL-terminated
+    const UnicodeString &ID=((Transliterator*) trans)->getID();
+    if(resultLength!=NULL) {
+        *resultLength=ID.length();
+    }
+    return ID.getBuffer();
+}
+
 U_CAPI int32_t U_EXPORT2
 utrans_getID(const UTransliterator* trans,
              char* buf,
@@ -301,6 +261,12 @@
 }
 
 U_CAPI void U_EXPORT2
+utrans_unregisterID(const UChar* id, int32_t idLength) {
+    UnicodeString ID(idLength<0, id, idLength); // r-o alias
+    Transliterator::unregister(ID);
+}
+
+U_CAPI void U_EXPORT2
 utrans_unregister(const char* id) {
     UnicodeString ID(id, ""); // use invariant converter
     Transliterator::unregister(ID);
@@ -341,6 +307,95 @@
                       char* buf, // may be NULL
                       int32_t bufCapacity) {
     return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, "");
+}
+
+/* Transliterator UEnumeration ---------------------------------------------- */
+
+typedef struct UTransEnumeration {
+    UEnumeration uenum;
+    int32_t index, count;
+} UTransEnumeration;
+
+U_CDECL_BEGIN
+static int32_t U_CALLCONV
+utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
+    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+        return 0;
+    }
+    return ((UTransEnumeration *)uenum)->count;
+}
+
+static const UChar* U_CALLCONV
+utrans_enum_unext(UEnumeration *uenum,
+                  int32_t* resultLength,
+                  UErrorCode *pErrorCode) {
+    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+        return 0;
+    }
+
+    UTransEnumeration *ute=(UTransEnumeration *)uenum;
+    int32_t index=ute->index;
+    if(index<ute->count) {
+        const UnicodeString &ID=Transliterator::getAvailableID(index);
+        ute->index=index+1;
+        if(resultLength!=NULL) {
+            *resultLength=ID.length();
+        }
+        // Transliterator keeps its ID NUL-terminated
+        return ID.getBuffer();
+    }
+
+    if(resultLength!=NULL) {
+        *resultLength=0;
+    }
+    return NULL;
+}
+
+static void U_CALLCONV
+utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
+    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+        return;
+    }
+
+    UTransEnumeration *ute=(UTransEnumeration *)uenum;
+    ute->index=0;
+    ute->count=Transliterator::countAvailableIDs();
+}
+
+static void U_CALLCONV
+utrans_enum_close(UEnumeration *uenum) {
+    uprv_free(uenum);
+}
+U_CDECL_END
+
+static const UEnumeration utransEnumeration={
+    NULL,
+    NULL,
+    utrans_enum_close,
+    utrans_enum_count,
+    utrans_enum_unext,
+    uenum_nextDefault,
+    utrans_enum_reset
+};
+
+U_CAPI UEnumeration * U_EXPORT2
+utrans_openIDs(UErrorCode *pErrorCode) {
+    UTransEnumeration *ute;
+
+    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+        return NULL;
+    }
+
+    ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
+    if(ute==NULL) {
+        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+
+    ute->uenum=utransEnumeration;
+    ute->index=0;
+    ute->count=Transliterator::countAvailableIDs();
+    return (UEnumeration *)ute;
 }
 
 /********************************************************************

--- tzdat.h DELETED ---