
                  ============================================
                   Martin Kiewitz's XtraRexx - Version v0.42b
                  ============================================

                             Released on 16.01.2005

                        Written and (c) by Martin Kiewitz
                            Dedicated to Gerd Kiewitz
-------------------------------------------------------------------------------

        This software is 'e-mail ware'. This means, if you use it, please send
         me an e-mail or a greeting card. I just want to see, how many people
         are using it.

  ============
  | FOREWORD |
  ============

        Well, I'm using REXX since 4-5 years. It's a very powerful language
         especially because of the DLL addon support. One may just write a
         simple OS/2-DLL and enhance REXX that way.

        I started doing XtraRexx 3 years ago. I enhanced it everytime I needed
         more functions especially for CGI programming. XtraRexx is now very
         powerful and offers all sorts of functions. I also implemented some
         "standard" functions, which are mostly included in almost any REXX
         extension DLL. Some important internal code is written in assembly
         language for absolute speed (6bit<->8bit, CRC calculation).
         Most of the code was done using IBM C.

        XtraRexx has especially fast template processing functions. They are
         meant for processing HTML templates - fill in variables, do loops
         and include/exclude parts of the file in the output. It's everything
         one needs and you still maintain control over it via REXX.

        XtraRexx v0.42 now also includes powerful Date/Time-functions for
         calculating with date and time data.

        Now I thought about releasing it to the public. I bet at least some
         programmers will start using it for CGI programming and such stuff.
         I wrote this documentation in around 3-4 hours, so please forgive
         typos.
         BTW. I won't release the source-code, at least for now - so don't ask.

        NOTE: This DLL is currently in-development and BETA software. I'm using
               it myself in a productive (web/2) environment - anyway, do so
               ONLY if you checked all functionality by yourself. I'm not
               responsible for broken servers, broken data or whatsoever. Also
               if there is a bug, please tell me. Anyway, don't rely on me
               fixing it within a few days.

  ================
  | INSTALLATION |
  ================

         Just copy XtraRexx.DLL into your \OS2\DLL directory. That's it.
         XtraRexx will always remain backward-compatible to prior versions.

         If you are a programmer, please use the XtraVersion API and check for
          the required version number like this:
           If XtraVersion()<"0.42" Then Do
              say "XtraRexx v0.42+ required."
              exit
           End

  ===================
  | BASIC FUNCTIONS |
  ===================

       ------------------------
        XtraLoadFuncs([quiet])
       ------------------------
       This is used to connect all functions automatically to REXX space.
        You may also specify the optional parameter "quiet" (case-sensitive) to
        disable the copyright message (for CGI usage).

       Reply:
        none

       Example:
        call RxFuncAdd "XtraLoadFuncs","XtraRexx","XtraLoadFuncs"
        call XtraLoadFuncs

       -----------------
        XtraDropFuncs()
       -----------------
       This is used to disconnect all functions automatically. It's not needed
        to use it.

       Reply:
        none

       ---------------
        XtraVersion()
       ---------------
       This is used to get the current version number of XtraRexx.

       Reply:
        XtraRexx Version number in the format "x.xx"

       Example:
        say XtraVersion() - would put "0.42" on the screen.

       -------------------------
        XtraSleep(Milliseconds)
       -------------------------
       This is used to sleep a specific amount of milliseconds.

       Reply:
        none

       Example:
        call XtraSleep 1000 - would sleep 1 second

       ----------------------
        XtraUnlock(Filename)
       ----------------------
       Will unlock a currently locked file. This is used for replacing DLL
        files w/o needing to use the locked file device driver functionality.

       Reply:
        "DONE", if action got done
        "NOTREQ", if action is not required (DLL not currently locked)
        "ERROR", if any error occured

       Example:
        say XtraUnlock("C:\OS2\DLL\XtraRexx.dll")

       --------------------
        XtraGetBootDrive()
       --------------------
       Will get the driveletter from the drive that the system booted from.

       Reply:
        "x:", where x is the drive-letter

       Example:
        say XtraGetBootDrive() - could put "C:" on the screen

       ------------------------------
        XtraGetPictureInfo(Filename)
       ------------------------------
       Will identify a picture and get the resolution of the picture as well
        The file is identified via binary analysation and not by looking at the
        filename-extension!

       Reply:
        "", if not identified
        "NNN RxRxR", where NNN is the type (JPG,PNG,GIF) and RxRxR is the
         resolution. The first R is the width in pixel, the second R is the
         height and the last R are the bits per pixel.

       Example:
        say XtraGetPictureInfo("test.jpg") - could reply "JPG 128x64x24"
            
       ----------------------
        XtraGetCRC32(String)
       ----------------------
       Will get the CRC32 value of the specified string.

       Reply:
        "FFFFFFFF", reply is always 8 chars hexadecimal code

       Example:
        say XtraGetCRC32("test") - would put "D87F7E0C" on the screen

       -----------------------------------
        XtraSwitchToSession(Session-Name)
       -----------------------------------
       Will switch focus to a session whose name begins with the given name.

       Reply:
        "OK", if operation succeeded
        "NOTFOUND", if session was not found

       Example:
        call XtraSwitchToSession "PMMail/2"
        /* would switch to PMMail/2 */

       ---------------------------------------------------------------
        XtraSetPosOfSession(Session-Name, VerticalPos, HorizontalPos)
       ---------------------------------------------------------------
       Will set the absolute position of a session "on-screen". This also
        works using multiple desktops and may be used to rearrange windows
        when starting up a system or even change position of windows after
        some time for displaying different stuff.

        VerticalPos: 0 means left-most
        HorizontalPos: 0 means lower-most

        The position given means the position of the lower-left edge of the
         window!

       Reply:
        "OK", if operation succeeded
        "NOTFOUND", if session was not found

       Example:
        call XtraSetPosOfSession "PMMail/2", 0, 0
        /* would put PMMail/2 at the left-most, lower-most position on the */
        /*  screen */

       -----------------------
        XtraIsDesktopLocked()
       -----------------------
       Will find out, if the desktop is currently locked.

       Reply:
        "LOCKED", if desktop locked
        "UNLOCKED", if desktop unlocked

       Example:
        say XtraIsDesktopLocked()
                                              
  ======================
  | TEMPLATE FUNCTIONS |
  ======================

       This specifies the 3 template functions used for processing e.g. HTML
        template files. Those files may contain template codes like this here:

        <!-- insert:value -->
         - Lets REXX code insert data using the name "value"

        <!-- incif:state1 -->
        <!-- else-incif:state1 -->
        <!-- end-incif:state1 -->
         - Lets REXX code choose wether to insert template data or not.
            REXX is only called on "incif". On "else-incif" XtraRexx will do
            the opposite action of what the REXX script told it on "incif".
            NOTE: else-incif also requires the *same* name. Also else-incif
                   may be ommited, if not needed.

        <!-- loop:table -->
        <!-- end-loop:table -->
         - Lets REXX code choose how often the loop shall be processed. It's
            also possible to skip the contents of the loop.

        All of these template codes are reentrant, which means you may specify
         a loop within a loop and so on.
        Template codes are CASE-SENSITIVE. You have to specify actions in
         lowcase (<!-- INCIF:xxx --> will NOT work).

        Now for the API:

       ----------------------------
        XtraTemplateInit(Filename)
       ----------------------------
       Will initiate template processing on a specific file. Will open the file
        for processing.

       Reply:
        "0", if open failed
        "1", if everything worked out

       Example:
        If XtraTemplateInit("test.html") Then Do
           say "Template file opened"
        End

       -----------------------
        XtraTemplateProcess()
       -----------------------
       This will process the template till end-of-file or till a template code
        is found that needs REXX processing. In that case, it will reply the
        template code. In any case, it will write any template data (but the
        codes of course) to STDOUT.

       Reply:
        "", when End-Of-File reached
        "ACTION:NAME", where ACTION is the action-type of the template code
                        and NAME is the name mentioned in it.

       Example:
        Do Forever
           SSI = XtraTemplateProcess()
           if Length(SSI)=0 Then leave

           Data = ""
           Select
             When SSI="insert:myvalue"           Then Data = "XtraRexx is great"
             Otherwise Nop
           End
           call CharOut ,Data
        End
        /* This here would process a template and insert "XtraRexx is great" */
        /*  as myvalue */

       ------------------------
        XtraTemplateDoAction()
       ------------------------
       This is used, when XtraRexx is told to actually process one iteration
        of a loop or process an "incif" template code. Calling it won't process
        it immediately. It will get processed when calling XtraTemplateProcess
        again.

       Reply:
        none

       Example:
        call XtraTemplateDoAction

       -------------------
        Big example code:
       -------------------
       This here is for showing you the usage of loop and incif codes.

        QuestCount   = 2
        Questions.1  = "Do you like XtraRexx?"
        Questions.2  = "Do you like OS/2?"
        QuestDisclaimer.1 = "YES"
        QuestDisclaimer.2 = "NO"

        say "Content-type: text/html"
        say ""
        call XtraTemplateInit "mytemplate.html"

        Do Forever
           SSI = XtraTemplateProcess()
           if Length(SSI)=0 Then leave
     
           Data = ""
           Select
             When SSI="insert:CGI_URL"           Then Data = CGI_URL
             When SSI="loop:quests"              Then Do
              CurQuest = 1
              If QuestCount>=CurQuest Then
                 call XtraTemplateDoAction
             End
             When SSI="end-loop:quests"          Then Do
              CurQuest = CurQuest+1
              If QuestCount>=CurQuest Then
                 call XtraTemplateDoAction
             End
             When SSI="insert:question"          Then Data = Questions.CurQuest
             When SSI="incif:disclaimer"         Then Do
              If QuestDisclaimer.CurQuest="YES"  Then
                 call XtraTemplateDoAction
             Otherwise Nop
           End
           call CharOut ,Data
        End

        Template-file:
         <tr>
          <td>
           <TABLE BORDER=1>
         
            <TR>
               <TD COLSPAN=7>
         <!-- loop:quests -->
                  <B><!-- insert:question --></B>
               </TD>
            </TR>
            <TR>
               <TD>&nbsp;</TD>
               <TD><font size="-2">yes</font></TD>
               <TD><font size="-2">no</font></TD>
               <TD>
                <!-- incif:disclaimer -->
                  <font size="-2">Disclaimer</font>
                <!-- end-incif:disclaimer -->
               </TD>
            </TR>
         <!-- end-loop:quests -->
           </TABLE>
          </td>
         </tr>

         I removed FORM code and so on to make it more readable. This example
          is only meant to get the feeling for it.

  ======================
  | DIRECT/C FUNCTIONS |
  ======================

       Direct/C are some conversion functions that I ported over from old
        sourcecode of mine. I'm using parts of it for BASE64 en/decoding in my
        e-mail filter REXX script - and the speed is faster than any tool or
        program that I got my hands on.

       ------------------------
        DirectC_CvWrd(String)
       ------------------------
       Will convert a 2-char string into a decimal value using Intel-ordering.

       Reply:
        "0", if the string length is not 2
        "x", where x is a decimal number ranging from 0 to 65535

       Example:
        say DirectC_CvWrd(D2C(1)||D2C(0))
        /* Will put "1" on the screen */
        say DirectC_CvWrd(D2C(0)||D2C(1))
        /* Will put "256" on the screen */

       ------------------------
        DirectC_CvDwd(String)
       ------------------------
       Will convert a 4-char string into a decimal value using Intel-ordering.

       Reply:
        "0", if the string length is not 4
        "x", where x is a decimal number ranging from 0 to 4294967295

       Example:
        say DirectC_CvWrd(D2C(1)||D2C(0)||D2C(0)||D2C(0))
        /* Will put "1" on the screen */
        say DirectC_CvWrd(D2C(0)||D2C(1)||D2C(0)||D2C(0))
        /* Will put "256" on the screen */

       ------------------------------
        DirectC_Set6bitTable(String)
       ------------------------------
       This enables the Encode/Decode From/To 6-bit functions. You need to give
        a 64-char string, so that XtraRexx is able to know what char to use.

       Reply:
        none

       Example:
        call DirectC_Set6bitTable "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
        /* Table used for BASE64 en/decoding */

       ------------------------------
        DirectC_EncodeTo6bit(String)
       ------------------------------
       Encodes an 8-bit string into 6-bit using the 6-bit table.

       Reply:
        The 6-bit string of course

       Example:
        say DirectC_EncodeTo6bit("test")
        /* Will put "dGVzdA" on the screen (when the 6-bit MIME table is used) */

       --------------------------------
        DirectC_DecodeFrom6bit(String)
       --------------------------------
       Decodes an 6-bit string into 8-bit using the 6-bit table.

       Reply:
        The 8-bit string of course

       Example:
        say DirectC_DecodeFrom6bit("dGVzdA")
        /* Will put "test" on the screen (when the 6-bit MIME table is used) */

       ------------------------------------------------------------------
        DirectC_EncodeTo6bitViaFile(InputFile, CharsPerLine, OutputFile)
       ------------------------------------------------------------------
       Encodes the contents of a whole 8-bit file and appends them onto a file.
       CharsPerLine defines how many chars will be ENCODED per ASCII output
        line. This is not the size of the output ascii line.

       Reply:
        Size of the new output file in decimal

       Example:
        call DirectC_EncodeTo6bitViaFile "test.exe", 1024, "test.mime"

       ---------------------------------------------------------------------------------
        DirectC_DecodeFrom6bitViaFile(InputFile, InputOffset, OutputFile, BoundaryLine)
       ---------------------------------------------------------------------------------
       Decodes the contents of a file (6-bit) into another file (8-bit).
        InputOffset is the offset from where decoding will start. The first
        char of a file has offset 1!

       One may also set a BoundaryLine to stop decoding when finding a line
        that *starts* using those characters (case-sensitive).
       When specifying "" as boundary, XtraRexx will decode till end-of-file.

       Reply:
        Offset within InputFile, where stream ends (1 based again)

       Example:
        call DirectC_DecodeFrom6bitViaFile "test.mime", 1, "test.exe", ""

  =======================
  | DATE/TIME FUNCTIONS |
  =======================

       Those functions were done for easy time/date calculation within REXX.

       Dates are 8-char strings in the format of "YYYYMMDD".
       Times are 4-char strings in the format of "HHMM".

       This format is great for saving, comparsion and sorting.
       e.g. to compare 2 dates simply use: If BeginDate>EndDate Then

       ----------------------
        XtraDateGetCurrent()
       ----------------------
       This simply gets the current date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateGetCurrent()
        /* This should put the current date in our internal format on the screen */

       ---------------------------
        XtraDateNormalize(String)
       ---------------------------
       This is used, when a user inputs a date and you want to analyse and
        extract his input. It may also be used for getting the date out of
        SysFileTree() data and so on. XtraRexx will use both short and long
        month names for analysation as well (ffs. XtraDateSetMonthNames).
        Also mentioning day types (monday, tuesday, etc.) is possible (ffs.
        XtraDateSetDayNames).

       The method used is quite complex and almost gets any date format that
        is possible. It's also intelligent in a way that you may simply specify
        just a day and XtraRexx will get the month and year for it.

       e.g. on 4th january 2005:
            specifying "5" will reply "20050105"
            specifying "4" will reply "20050204"
            specifying "4 12" will reply" 20051204"

       It's also possible to tell XtraRexx to walk backwards using "-".

       e.g. on 4th january 2005:
            specifying "5-" will reply "20041205"
            specifying "4-" will reply "20050104"
            specifying "4 12-" will reply "20041204"

       Specifying an empty string will reply the current date.

       Reply:
        "YYYYMMDD"
        or "", if date invalid (or not extractable)

       Example:
        say XtraDateNormalize("1 nov 2005")
        /* This should put "20051101" on the screen */
        say XtraDateNormalize("11/1/2005")
        /* This should put "20051101" on the screen */

       ---------------------------------
        XtraDateAddDays(Date, DayCount)
       ---------------------------------
       This is used, when adding days to a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateAddDays("20050104", 5)
        /* This should put "20050109" on the screen */

       ---------------------------------
        XtraDateSubDays(Date, DayCount)
       ---------------------------------
       This is used, when subtracting days from a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateSubDays("20050104", 5)
        /* This should put "20041230" on the screen */

       -------------------------------------
        XtraDateAddMonths(Date, MonthCount)
       -------------------------------------
       This is used, when adding months to a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateAddMonths("20050104", 5)
        /* This should put "20050604" on the screen */

       -------------------------------------
        XtraDateSubMonths(Date, MonthCount)
       -------------------------------------
       This is used, when subtracting months from a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateSubMonths("20050104", 5)
        /* This should put "20040804" on the screen */

       -------------------------------------
        XtraDateAddYears(Date, YearCount)
       -------------------------------------
       This is used, when adding years to a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateAddYears("20050104", 5)
        /* This should put "20100104" on the screen */

       -------------------------------------
        XtraDateSubYears(Date, YearCount)
       -------------------------------------
       This is used, when subtracting years from a date.

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateAddYears("20050104", 5)
        /* This should put "20000104" on the screen */

       -----------------------
        XtraDateGetType(Date)
       -----------------------
       This is used to get the type of a date.

       Reply:
        "x", where 1 is monday and 7 is sunday.

       Example:
        say XtraDateGetType("20050104")
        /* This should put "2" (Tuesday) on the screen */

       ----------------------------------
        XtraDateAddType(DateType, Count)
       ----------------------------------
       This is used, when adding to a datetype.

       Reply:
        "x", where 1 is monday and 7 is sunday.

       Example:
        say XtraDateAddType(2, 6)
        /* This should put "1" (Monday) on the screen */

       ----------------------------------
        XtraDateSubType(DateType, Count)
       ----------------------------------
       This is used, when subtracting from a datetype.

       Reply:
        "x", where 1 is monday and 7 is sunday.

       Example:
        say XtraDateSubType(2, 6)
        /* This should put "3" (Wednesday) on the screen */

       ----------------------------------------
        XtraDateGetNextTypeDay(Date, DateType)
       ----------------------------------------
       This gets the following date after the specified date that has the given
        type. This never replies with the given Date!

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateGetNextTypeDay("20050104", 2)
        /* This should put "20050111" on the screen */

       --------------------------------------------
        XtraDateGetPreviousTypeDay(Date, DateType)
       --------------------------------------------
       This gets the previous date before or equal the given date that has the
        given type. This MAY reply the given date!

       Reply:
        "YYYYMMDD"

       Example:
        say XtraDateGetPreviousTypeDay("20050104", 2)
        /* This should put "20050104" on the screen */

       ----------------------------
        XtraDateGetMonthDays(Date)
       ----------------------------
       This gets the total amount of days in the specified month.

       Reply:
        "x"

       Example:
        say XtraDateGetMonthDays("20050104")
        /* This should put "31" on the screen */

       ----------------------------------------------------------
        XtraDateGetDaysBetween(Date, [Time,] 2ndDate [,2ndTime])
       ----------------------------------------------------------
       This gets the total amount of days inbetween 2 dates. One may also
        specify an additional Time for those days to be more accurate. This is
        meant for getting the exact days and minutes between 2 time-locations.

       Reply:
        "x"

       Example:
        say XtraDateGetDaysBetween("20050104", "20050105")
        /* This should put "1" on the screen */
        say XtraDateGetDaysBetween("20050104", "2300", "20050105", "0100")
        /* This should put "0" on the screen (cause its only 2 hours) */

       -----------------------------
        XtraDateGetMonthName(Month)
       -----------------------------
       This gets the current month name for the specified month. XtraRexx
        automatically uses english names, but you may specify different ones
        using XtraDateSetMonthNames().

       Reply:
        "", if invalid month specified
        otherwise the month name e.g. "January"

       Example:
        say XtraDateGetMonthName("1")
        /* This should put "January" on the screen */

       --------------------------------------
        XtraDateSetMonthNames(MonthNameList)
       --------------------------------------
       This is used to set all month names. They need to be separated by '|'.

       Reply:
        none

       Example:
        call XtraDateSetMonthNames("Januar|Februar|Mrz|April|Mai|Juni|Juli|August|September|August|Oktober|November|Dezember"
        /* This sets German month names */

       ----------------------------------
        XtraDateGetMonthShortName(Month)
       ----------------------------------
       This gets the current short month name for the specified month. XtraRexx
        automatically uses english names, but you may specify different ones
        using XtraDateSetMonthShortNames().

       Reply:
        "", if invalid month specified
        otherwise the month name e.g. "Jan"

       Example:
        say XtraDateGetMonthShortName("1")
        /* This should put "Jan" on the screen */

       -------------------------------------------
        XtraDateSetMonthShortNames(MonthNameList)
       -------------------------------------------
       This is used to set all short month names. They need to be separated by
        '|'.

       Reply:
        none

       Example:
        call XtraDateSetMonthShortNames("Jan|Feb|Mr|Apr|Mai|Jun|Jul|Aug|Sep|Aug|Okt|Nov|Dez"
        /* This sets German month names */

       -------------------------
        XtraDateGetDayName(Day)
       -------------------------
       This gets the current day name for the specified month. XtraRexx
        automatically uses english names, but you may specify different ones
        using XtraDateSetDayNames().

        Note: This uses the day-type (1-7) as input *not* the day-number.

       Reply:
        "", if invalid day-type specified
        otherwise the day name e.g. "Monday"

       Example:
        say XtraDateGetDayName("1")
        /* This should put "Monday" on the screen */

       ------------------------------------
        XtraDateSetDayNames(MonthNameList)
       ------------------------------------
       This is used to set all day names. They need to be separated by
        '|'.

       Reply:
        none

       Example:
        call XtraDateSetDayNames("Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag|Sonntag"
        /* This sets German day names */

       ------------------------------
        XtraDateGetDayShortName(Day)
       ------------------------------
       This gets the current short day name for the specified month. XtraRexx
        automatically uses english names, but you may specify different ones
        using XtraDateSetDayShortNames().

        Note: This uses the day-type (1-7) as input *not* the day-number.

       Reply:
        "", if invalid day-type specified
        otherwise the day name e.g. "Mon"

       Example:
        say XtraDateGetDayShortName("1")
        /* This should put "Mon" on the screen */

       -----------------------------------------
        XtraDateSetDayShortNames(MonthNameList)
       -----------------------------------------
       This is used to set all short day names. They need to be separated by
        '|'.

       Reply:
        none

       Example:
        call XtraDateSetDayShortNames("Mo|Di|Mi|Do|Fr|Sa|So"
        /* This sets German day names */

       ----------------------------
        XtraDateFormat(Date, Type)
       ----------------------------
       This is used to get a displayable string out of a given date.
       Type is a string that defines the output format.

       Reply:
        Output format is listed after the output type:
          ""/"NORMAL"  : "1.1.2005"
          "ZEROED"     : "01.01.2005"
          "SHORT"      : "1.1.05"
          "SHORTZEROED": "01.01.05"
          "LETTER"     : "1. January 2005"
          "SHORTLETTER": "1. Jan 2005"

       Example:
        say XtraDateFormat("20050104", "")
        /* This should put "4.1.2005" on the screen */

       ------------------------
        XtraDateValidate(Date)
       ------------------------
       This is used to validate a given date. Note that this is meant for
        usage on the internal format only e.g. checking HTML-POST replies etc.

       Reply:
        "VALID", if date is valid
        "INVALID", if date is invalid

       Example:
        say XtraDateValidate("20050104")
        /* This should put "VALID" on the screen */
        say XtraDateValidate("20050100")
        /* This should put "INVALID" on the screen */

       ----------------------
        XtraTimeGetCurrent()
       ----------------------
       This simply gets the current time.

       Reply:
        "HHMM"

       Example:
        say XtraTimeGetCurrent()
        /* This should put the current time in our internal format on the screen */

       ---------------------------
        XtraTimeNormalize(String)
       ---------------------------
       This is used, when a user inputs a time and you want to analyse and
        extract his input. It may also be used for getting the time out of
        SysFileTree() data and so on.

       The method used is quite complex and almost gets any time format that
        is possible. It's also intelligent in a way that you may simply specify
        just a minute and XtraRexx will get the hour for it.

       e.g. on 14:04
            specifying "5" will reply "1405"
            specifying "4" will reply "1504"

       It's also possible to tell XtraRexx to walk backwards using "-".

       e.g. on 14:04:
            specifying "5-" will reply "1305"
            specifying "4-" will reply "1304"

       Specifying an empty string will reply the current time.

       Reply:
        "HHMM"
        or "", if time invalid (or not extractable)

       Example:
        say XtraTimeNormalize("13 20")
        /* This should put "1320" on the screen */

       ---------------------------------------
        XtraTimeAddMinutes(Time, MinuteCount)
       ---------------------------------------
       This is used, when adding minutes to a time.

       Reply:
        "HHMM"

       Example:
        say XtraTimeAddMinutes("1404", 5)
        /* This should put "1409" on the screen */

       ---------------------------------------
        XtraTimeSubMinutes(Time, MinuteCount)
       ---------------------------------------
       This is used, when subtracting minutes from a time.

       Reply:
        "HHMM"

       Example:
        say XtraTimeSubMinutes("1404", 5)
        /* This should put "1359" on the screen */

       -----------------------------------
        XtraTimeAddHours(Time, HourCount)
       -----------------------------------
       This is used, when adding hours to a time.

       Reply:
        "HHMM"

       Example:
        say XtraTimeAddHours("1404", 5)
        /* This should put "1904" on the screen */

       ---------------------------------------
        XtraTimeSubMinutes(Time, HourCount)
       ---------------------------------------
       This is used, when subtracting hours from a time.

       Reply:
        "HHMM"

       Example:
        say XtraTimeSubHours("1404", 5)
        /* This should put "0904" on the screen */

       ----------------------------------------------------------
        XtraTimeGetMinutesBetween(Time, [Date,] 2ndTime [,2ndDate])
       ----------------------------------------------------------
       This gets the total amount of minutes inbetween 2 times. One may also
        specify an additional Date for those times to be more accurate. This is
        meant for getting the exact days and minutes between 2 time-locations.

       Reply:
        "x"

       Example:
        say XtraTimeGetMinutesBetween("1409", "1422")
        /* This should put "13" on the screen */
        say XtraTimeGetMinutesBetween("20050104", "2300", "20050105", "0100")
        /* This should put "120" on the screen */

       ----------------------------
        XtraTimeFormat(Time, Type)
       ----------------------------
       This is used to get a displayable string out of a given time.
       Type is a string that defines the output format.

       Reply:
        Output format is listed after the output type:
          ""/"NORMAL"  : "1:03"
          "ZEROED"     : "01:03"
          "POINTED"    : "1.03"
          "POINTEDZERO": "01.03"

       Example:
        say XtraTimeFormat("1404", "")
        /* This should put "14:04" on the screen */

       ------------------------
        XtraTimeValidate(Time)
       ------------------------
       This is used to validate a given time. Note that this is meant for
        usage on the internal format only e.g. checking HTML-POST replies etc.

       Reply:
        "VALID", if date is valid
        "INVALID", if date is invalid

       Example:
        say XtraDateValidate("1404")
        /* This should put "VALID" on the screen */
        say XtraDateValidate("2400")
        /* This should put "INVALID" on the screen */

       -------------------------------------------
        XtraTimeSetDurationNames(NameList)
       -------------------------------------------
       This is used to set all duration names. They need to be separated by '|'.
        XtraRexx defaults to english and uses "days|day|hours|hour|minutes|minute".

       Reply:
        none

       Example:
        call XtraTimeSetDurationNames "Tage|Tag|Stunden|Stunde|Minuten|Minute"
        /* This sets German names */

       -------------------------------------------
        XtraTimeFormatDuration([Days,] Minutes)
       -------------------------------------------
       This is used to get a displayable string out of a given duration.
        You may specify a day-count optionally. The output will only contain
        data, that is not equal 0.

        Note: This is meant to be used after the XtraDateGetDaysBetween()/
               XtraTimeGetMinutesBetween()-functions.

       Reply:
        none

       Example:
        say XtraTimeFormatDuration(0, 60)
        /* This should put "1 hour" on the screen */
        say XtraTimeFormatDuration(60)
        /* This should put "1 hour" on the screen */
        say XtraTimeFormatDuration(1, 59)
        /* This should put "1 day, 59 minutes" on the screen */
        say XtraTimeFormatDuration(1, 61)
        /* This should put "1 day, 1 hour, 1 minute" on the screen */

  ===========
  | CONTACT |
  ===========

        There were several ways to contact me.
        Just try 'jimi@klinikum-konstanz.de'.
         Please DO NOT POST THIS E-MAIL TO USENET NOR THE WEB!!!

        My official homepage is at: http://www.ecomstation.ru/kiewitzsoft/

        I'm dedicating XtraRexx to my father.
