locale12.zip - Locales support for DOS,Win3x,Win32

The C-source codes of POSIX-compatible locales for DOS,
Windows 3.x, Win32.  Version 1.2

This sources was successfully tested with few versions of
Borland C, Microsoft C, Watcom C and DJGPP v2 and can be easy ported
on other cmpilers.
This software works (and tested) under
all OS from MS-DOS 3.30 to Windows NT 4.0.


Copyright (c) 1995-1997  by Timofei Bondarenko

License agreements
------------------
This is free software. It may be used or distributed in any form,
as long as you:
1) left unchanged any copyrights inside;
2) if you modify a source, a your copyright notice to
   the modificaion must be added;
3) if you use this software in a package or a binary, you
   must give credit to me and point to accessibility of my
   sources.

Finally, when you employ this software in a your final product
please notify me in couple lines about. And of course, NO WARRANTY.

---------------------------------------------------------------------------


How to contact
--------------
All your notes are welcomed. Feel free to write me at   tim@ipi.ac.ru
-------------------------------------------------------===============

How to use
----------
   The small library (named locale.lib) provides the actual
locale-dependent information according POSIX rules under DOS,
Windows 3.x and Win32. The service is very similar on all three OS.

No environment variables used (because it is not a general way
under DOS/Windws). No additional databases or buil-in data used -
for clarity. All information obtained from OS only.

The locale-dependent information includes date, time and monetary
formats, character classification (isupper(), islower(), isalpha(),
isprint(), isgraph(), sometime ispunct() and isspace());
character convertion (toupper(), tolower() and strupr(), strlwr())
string sorting (strcoll(), strxfrm());
time representation (strftime(), strptime());
numeric & monetary representation (strfmon()).

Full list of the supported functions and details
contained in file "locale.h".

NOTE,  using of vendor supplied <locale.h> is preffered unless you
use some internals, like _lc_Coll2, _lc_tolower etc.

The couple functions in spirit of System V hasn't documented in
most DOS/Windows compilation system. See an UNIX man if possible.
Here short description followed.

strptime() - is "backward strftime" with following exceptions:
~~~~~~~~~~   %A is same as %a as well as %B and %b;
             string comparision is case-insensitive;
             white-space characters treated as in printf() family.
Non recognized and non specified in format line fields of 'struct tm'
left unchanged. Any checking for validate a date has not performed,
see strptime.c for details.

strfmon() - formatting of monetary values according to localeconv()
~~~~~~~~~   (like printf()).

Valid format specifiers are:
%i - international currency amount representation;
%n - national currency amount representation;
%f - (my extention!) national non-monetary amount representation.

For all convertions the "double" arguments required!

Valid flags are

!     suppress the currency symbol;

+     use mandatory sign for numeric,
      use lconv::positive_sign and lconv::negative_sign instead of
      parentheses for monetary;

^     do not use grouping;

=*    the actual flag is '='. * mean an charactater which will be used
      as "the numeric fill character" if flag '#' also specified;

#p    a # followed by a decimal number, specifying the "left
      precesion", number of digits to be formatted to the left of the
      decimal point. "the numeric fill character" (by defauls is
      space) to fill it. Grouping is never applied this filling;

-     left alignment, as in printf();

w     a decimal number = field's width, as in printf();

.r    '.' followed by a decimal number = right precesion, as in printf().

-------------------------------------------------------------------------

NOTES:
  *)   This library can be compiled for 4 different modes:
          a) DOS;
          b) Windows 3.x;
          c) Windows 3.x with ole2nls.dll (shipped within Win32s);
          d) Win32.
    These modes works somewhat differently.
    Only 8-bits chararacters are supported.
    See also config.h for compile-time options.
  *)   The setlocale() always accepts locales "C" and "".
       For DOS also possible locales like as "PPPPCCCC", where CCCC is
    decimal Country Code and PPPP is decimal Code Page; 9999 mean the
    current value i.e. "99999999" is equivalnet to "". For example
    "04370001" mean USA locale, "08660007" - Russia, etc...
    Under MS-DOS CodePage 0 also allowed: that mean default code page
    for a specified country (i.e. "1" is same as "04370001"), but
    under DR-DOS CodePage 0 will crash your system.
       For Windows 3.x without ole2nls only "C" and "" allowed, where
    "" assume formats from Control Panel which depends of localization
    of Windows, also statement win.ini/Intl/sLanguage=...  can be used.
       For Win32 and Win3x with OLE2NLS setlocale() can accepts
    value of a LCID in form "%08lX".
  *)   Categories LC_NUMERIC and LC_MONETARY are not linked by default.
    For use them you must make a call of localeconv() at least once
    before setlocale(). This trick saves about 10% of codesize and not
    violate other rules (You can to call localeconv() in the first line
    of your main() and forget). See also config.h for details.
  *)   For DOS possible only english and russian months and weekdays names,
    because DOS hasn't provide these names but english names are used in
    "C" locale (and therefore are mandatory) and russian is simple my
    native language :)
       For Win3x without ole2nls.dll - thats names accessible in english
    and in one another language dependent from localization of main.cpl.
  *)   For Windows can be used an OEM-charset or Win-125X charset
    selected at compile-time or run-time switch _lc_Win (see below and
    config.h).
  *)   See below few tables for comparison / conversion of characters.
  *)   The strcoll() / strxfrm() can do 1- or 2- pass comparison. In case
    of 2-pass the string generated by strxfrm() will be longer than source
    string. See below _lc_Coll2.
  *)   In addition to standard UNIX/POSIX/ANSI-C routines as
    setlocale(), localeconv(), strftime(), strptime(), strfmon(),
    strcoll(), strxfrm(), toupper(), tolower(), isXXXX()  also
       Provided few non-standard but usable and popular functions:
    strupr(), strlwr(), stricoll(), stricmp(), strnicmp().
       Sorry, scanf() and printf() kinds (dependent on LC_NUMERIC)
    are not implemented...
  *)   Note, some compilers has macros for toupper(), tolower() which
    might works incorrectly. These functions and macro isXXXX() in many
    cases can't works with 'signed char'. Use 'unsigned char' or 'int in
    range EOF ... UCHAR_MAX', as returned by getchar() etc.
  *)   WARNING: About 1024 kB of Stack required in some configurations.
  *)   You can to adjust values of categories LC_XXXX according your
    compiler/header/libraries to avoid conflicts between this header
    and your standard <locale.h>.

-------------------------------------------------------------------------

HOw to build:
-------------
1) Go to subdirectory named LOCALE.
2) Look up files config.h and locale.h. These files contains
   actual information about building modes and compile-time options.
3) Edit the "makefile" for desired platform (makefile.dj for DJGPP)
   and run your MAKE.
4) Make sure that you are using in your functions from builded
   locale.lib instead your standard SDK.
5) There is QUCK&DIRTY test
   program, named test.c

WARNINGS for DJGPP:
DJGPP uses layout of 'struct lconv' completly incompatible with
declared here and in most (all?) other compilers (yes, for UNIX so).
Therefore you should define USE_NATIVE_INTERFASE.

Also DJGPP's 'struct lconv' hasn't mon_thousands_sep - poor POSIX...

DJGPP v2 contain a bug: tzname[] has invalid values which cause GPF.
You can use workaround written by
                 Michael Mauch  [ e-mail: michael.mauch@gmx.de ]
The subdirectory PATH contains his patch.


DOS
---
   For accessing to the actual information you must use COUNTRY
statement in your CONFIG.SYS. That is not decrease amount of memory,
but simple change DOS defaults from USA to the specified locale.
   For changing locales "on the fly" you should load NLSFUNC and
probally DISPLAY.SYS. Subdirectory UTILS contains some useful
tools for it.

Win3x
-----
   I think COMPAT31=1 and USE_OLENLS is undefined are most
prefferable combination because it works quite well on both
Windows 3.x and Windoes 95/NT.
   Only "C" and "" locales will be allowed but you can play
with ControlPanel/International, win.ini/Intl/* and in some
cases with win.ini/Intl/sLanguage.

TIME
----
   Borland's and Microsoft's standard libraries contains tzset() which
can't handle non-USA DST rules. Subdirectory TIME contains more correct
version of this function and simple utility for automatic switch
your computer's clock to/from DST.
This patch isn't required for DJGPP and Watcom C.
------------------------------------------------------------------------