XE V1.33/2012 XE is used in batch programs for DOS and in DOS
FREEWARE      windows of Windows 95/98/ME/NT/2000. It works similar
              to the ECHO command, however, using replacement
              parameters it is possible to send specific characters
              to the screen. In addition, several new functions are
              introduced (see below).
              The output text can be re-directed into a file.
              The number sign # is used to start replacement para-
              meters. % parameters can be used in the same way as
              with the ECHO command.

Invocation example: XE Comment 1 :Info -#3E Tiger#; Comment 2
Screen output:      Info -> Tiger

The first colon starts the screen output,
#; stops the screen output

#00 to #FF   serves as replacement for the hex value of a character
             to be output

#3E >    #7C |    #1B <ESC>    #0C FF  (Form Feed)
#3C <    #25 %    #09 <TAB>    #07 BEL (Bell)
#22 "    #26 &    #27 '        #40 @
#0D CR alone      #0A LF alone         #5E ^

#V  additional new line output (CR+LF)
#P  no CR+LF at the end of the line
##  outputs # once
#G  sends time and date stamp to the screen (German)
#$  sends time and date stamp to the screen (English)
#H  sends only the time stamp to the screen
#;  as of here the command line is no longer evaluated (comment)

Other functions:
----------------
#=G Synchronization to the next full second (waits until the next
    new second,
    on a key stroke: abortion and errorlevel 100
#=H Deletion of the keyboard buffer, generates errorlevel 0 or 1:
    Errorlevel 0, if the buffer was empty
    Errorlevel 1, if the buffer contained characters
#X or #=X Bell sound, output directly via BIOS, i.e. no redirec-
    tion is possible as a character into a file
#U  Sound 880 Hz, short
#W  Sound 440 Hz, long
#=Y Clear Screen
#Z or #=Z No prompt on a key call (see next)
#_\ outputs current drive letter
#\  outputs current directory (with a \ at the end)

#[...] Key call
---------------------------------------------------------------
Between the brackets [] the characters A...Z, 0...9 and SPACE
can be inserted. The program waits for an entry from the key-
board. If the entered character is equal to one of the characters
inserted between the brackets, the program is continued and an
errorlevel (1...n) is generated. The position of the character
between the [] determines the value of the errorlevel produced.
A...Z means the same as a...z. If SPACE is defined between the [],
the entry of the ENTER key causes the same as the SPACE key.
Instead of 0..9, the function keys F1..F10 can also be
used (0=F10).

Example:   XE :#[d7T ]
Result:    D or d  produce errorlevel 1
           7 or F7 produce errorlevel 2
           T or t  produce errorlevel 3
           SPACE or ENTER key produce errorlevel 4
           ESC     produces errorlevel 0 (fixed setting)
A maximum of 40 characters may be inserted between the brackets.
If characters are used several times, only the first ones are valid.
Example:   XE :#[A 5 u a]
Result:    A or a  produce  errorlevel 1
           SPACE or ENTER key produce errorlevel 2
           5 or F5 produce errorlevel 3
           U or u  produce errorlevel 5
           ESC     produces errorlevel 0 (fixed setting)
           Errorlevels 4, 6 and 7 can never be produced because
                               SPACE and 'a' are used several times.
If a preselected key is pressed, the entered character is output to
the screen. Instead of ESC, SPACE or ENTER always a SPACE is output.
If this sreen output is not desired, it can be suppressed by
inserting #=Z (or #Z) at the beginning of the command line.
Example:   XE :#=ZTextText#[ABC123 ]More text
Output:    TextTextMore text  (the keyboard entry has no effect to
                               the screen output)
Special feature: If no character is inserted between [], any key
is accepted and errorlevel 0 is generated (like with ESC).

#(...) Cursor control
-------------------------------------------------------------------
Invocation of #(...) (Cursor control) results in changing shape
and/or position of the cursor. Examples:

 #(N) or #(ON)   Cursor is turned on  (VGA and higher)
 #(F) or #(OFF)  Cursor is turned off (VGA and higher)
 #(V) or #(VGA)  Standard setting for VGA and higher (also MCGA)
 #(C) or #(CGA)  Standard setting for CGA and higher
 #(M) or #(MDA)  Standard setting for MDA, HERCULES, EGA
 #(B) or #(BIG)  Big  cursor
 #(-)            Thin cursor
 #(+)            Wide cursor
 #(X46) Cursor jumps to the 46th column (counts from 1 to 80)
 #(Y17) Cursor jumps to the 17th row (counts from 1 to 25)
 #(R)   Stores (saves) current cursor position in memory 0
 #(S)   Puts cursor to position stored in memory 0
 #(T)   Stores (saves) current cursor position in memory 1
 #(U)   Puts cursor to position stored in memory 1
 #(W)   Shifts cursor one position up but not beyond the screen
 #(E)   Shifts cursor one position down but not beyond the screen
 #(P)   Shifts cursor one position to the left  (but not beyond...)
 #(Q)   Shifts cursor one position to the right (but not beyond...)

 It is possible to specify several parameters within one command,
 e.g.  XE :#(FX53Y12R)Hello#(SN)

In the DOS box of Windows NT/2000, the cursor control is limited.
Only cursor movements as well as storing and recovering of cursor
position work correctly. 
Hiding the cursor or setting to display standards (VGA, CGA etc.)
do not work with the emulated DOS box of Windows NT/2000.

#=(...) Call upon an entry of a character string
-----------------------------------------------
Between the brackets of #=(...) a complete path name of a file must
be entered. This function waits for a string entered via the key-
board and terminated with <Enter>. The maximum length of the string
is 128 characters. The string is then stored in the specified file.
The last two characters in the file are CR/LF. If this file is exe-
cutable as a batch program, it can be run from a just running batch
program using the CALL command.

#{...} Insertion of a text string from a file
--------------------------------------------------------------------
Between the brackets of #{...} the complete path name of that file
must be inserted, from which the text string is to be taken in order
to send it to the screen. From the file, only a maximum of 128 char-
acters are considered. Possibly existing CTRL-Z or CR/LF characters
are omitted.
  
Example: XE :#{C:\TEXTS\SPECIAL\WRITE.TXT}

File names and directory names must meet the DOS specifications.
Long file names are not accepted. If the given file is not found,
nothing will be sent to the screen (neither an error message).

#={...} Insertion of the contents of a file
--------------------------------------------------------------------
Between the brackets of #={...} the complete path name of that file
must be inserted, from which the contents is to be taken in order
to send it to the screen. If the file contains TABs, these are re-
placed by a suitable number of blanks. The file may be of any length.
  
Example: XE :#={C:\TEXTS\SPECIAL\WRITE.TXT}

File names and directory names must meet the DOS specifications.
Long file names are not accepted. If the given file is not found,
nothing will be sent to the screen (neither an error message).

#+...+ Wait (delay)
---------------------------------------------------------------
Between the two plus signs of #+...+ a number (1 to 65535) must
be inserted. The wait function starts a delay (time base is sec-
onds). If a key is pressed during the delay time, the wait func-
tion will be aborted and the errorlevel 100 will be set.
Numbers greater than 65535 will cause undefined results.
Invocation example: XE :#+25+
The plus sign at the end of the inserted number must not be for-
gotten. Otherwise the function will not work correctly.

#I...+ Wait (count-down)
---------------------------------------------------------------
Between the two characters I and + of #I...+ a number (1 to 65535)
must be inserted. This wait function starts a delay (time base is
seconds) as a visible count-down. If a key is pressed during the 
delay time, the wait function will be aborted and the errorlevel
100 will be set.
Numbers greater than 65535 will cause undefined results.
Invocation example: XE :#I25+
The plus sign at the end of the inserted number must not be for-
gotten. Otherwise the function will not work correctly.

#-...- Waiting for a given time (of day)
---------------------------------------------------------------
Between the two minus signs of #-...- a time (of day)
(00:00 to 23:59) must be inserted. This function starts a delay,
which expires at the given time. If a key is pressed during the
delay time, the wait function will be aborted and the errorlevel
100 will be set.
Given time stamps, which are invalid, will cause undefined results.
Please note, that hours and minutes must be given in two digits each.
Invocation example: XE :#-00:09-
                or: XE :I am waiting until 09:05 #-09:05- #$
In the second example, the time stamp is sent to the screen after
the time has elapsed (for checking the correct function).
The minus sign at the end of the inserted time must not be for-
gotten. Otherwise the function will not work correctly.

Working with variables (mainly used with counters and timers)
-------------------------------------------------------------
The XE program works with two variables, which can have sizes of
-32767...0...+32767 as signed integers. The two variables are ad-
dressed with #!.... (variable 1) and #:.... (variable 2).
The following examples show the possible applications.
The numbers can be specified with or without sign, e.g. 200 or +200
(positive number) or -200 (negative number):

#!-200! Variable 1 is set to -200
#!N     Variable 1 is negated (sign - instead of + or vice versa)
#!=     Variable 1 is sent to the screen (with sign plus 5 digits)
#!D     Variable 1 is sent to the screen (only the digits needed)
#!_     Variable 1 is processed as an amount of seconds and displayed
        in the format HH:MM:SS (hours:minutes:seconds)
        (variable 1 must be a positive number here, 0...+32767)
#!6548? Variable 1 is compared to the number +6548. Result:
          Errorlevel 3 if variable 1 is greater than the number
          Errorlevel 2 if variable 1 is equal to the number
          Errorlevel 1 if variable 1 is less than the number
#!34+   Variable 1 is increased by 34
#!72-   Variable 1 is decreased by 72
#!-32*  Variable 1 is multiplied by -32
#!18/   Variable 1 is divided by 18, the result is rounded down
          to a signed integer
#!K     Variable 1 is entered on the keyboard.
          Example: XE :How many copies to print? #!K#!= copies
          After invocation with #!K a number of -32767...0...32767
          is to be entered on the keyboard. Other values cause errors.
          The entry is terminated by the ENTER key. After pressing
          the ENTER key, the cursor moves back to the first position
          of the entered number.
#!L     The internal errorlevel (while XE is running) is copied to
          variable 1.
#!M     An errorlevel (0...255) is created from variable 1.
          If variable 1 exceeds this range, the Lower Byte is used to
          create the errorlevel. Variable 1 is not changed by this
          action.
#!{...} Variable 1 is loaded from that file, whose name is inserted
          between the brackets {}. Example: XE #!{C:\XE\VAR1.VAR}
          The specified file must contain a valid number
          -32767...+32767.
          Examples for file contents:  5   -67  +00008  -056
          For more information read the file VAR_E.VAR.
#!(...) Variable 1 is copied to that file, whose name is inserted
          between the brackets (). Example: XE #!(C:\XE\VAR1.VAR)

#:200:  Variable 2 is set to +200
#:N     Variable 2 is negated (sign - instead of + or vice versa)
#:=     Variable 2 is sent to the screen (with sign and 5 digits)
#:D     Variable 2 is sent to the screen (only the digits needed)
#:_     Variable 2 is processed as an amount of seconds and displayed
        in the format HH:MM:SS (hours:minutes:seconds)
        (variable 2 must be a positive number here, 0...+32767)
#:-548? Variable 2 is compared to the number -548. Result:
          Errorlevel 3 if variable 2 is greater than the number
          Errorlevel 2 if variable 2 is equal to the number
          Errorlevel 1 if variable 2 is less than the number
#:34+   Variable 2 is increased by 34
#:72-   Variable 2 is decreased by 72
#:50*   Variable 2 is multiplied by 50
#:-18/  Variable 2 is divided by -18, the result is rounded down
          to a signed integer
#:K     Variable 2 is entered on the keyboard.
          Further description see #!K
#:L     The internal errorlevel (while XE is running) is copied to
          variable 2.
#:M     An errorlevel (0...255) is created from variable 2.
          If variable 2 exceeds this range, the Lower Byte is used to
          create the errorlevel. Variable 2 is not changed by this
          action.

#:{...} Variable 2 is loaded from that file, whose name is inserted
          between the brackets {}. Example: XE #:{C:\XE\VAR2.VAR}
          Further description see #!{...}
#:(...) Variable 2 is copied to that file, whose name is inserted
          between the brackets (). Example: XE #:(C:\XE\VAR2.VAR)

#!:+    Variable 1 is increased by the value contained in variable 2
#!:-    Variable 1 is decreased by the value contained in variable 2
#!:*    Variable 1 is multiplied by the value contained in variable 2
#!:/    Variable 1 is divided by the value contained in variable 2,
          the result is rounded down to a signed integer
#!:!    Variable 1 is exchanged with variable 2
#!:?    Variable 1 is compared to variable 2. Result:
          Errorlevel 3 if variable 1 is greater than variable 2
          Errorlevel 2 if variable 1 is equal to variable 2
          Errorlevel 1 if variable 1 is less than variable 2
#!:_    Variable 1 copies the value from variable 2,
          variable 2 remains unchanged

#!:\    Variable 1 is divided by the value contained in variable 2.
          Results: variable 1 contains the result of division
                   variable 2 contains the undevided rest (modulo)

#:!+    Variable 2 is increased by the value contained in variable 1
#:!-    Variable 2 is decreased by the value contained in variable 1
#:!*    Variable 2 is multiplied by the value contained in variable 1
#:!/    Variable 2 is divided by the value contained in variable 1,
          the result is rounded down to a signed integer
#:!:    Variable 2 is exchanged with variable 1
#:!?    Variable 2 is compared to variable 1. Result:
          Errorlevel 3 if variable 2 is greater than variable 1
          Errorlevel 2 if variable 2 is equal to variable 1
          Errorlevel 1 if variable 2 is less than variable 1
#:!_    Variable 2 copies the value from variable 1,
          variable 1 remains unchanged

The contents of the variables are lost when the computer is rebooted
or in case of warm or cold start. If the DOS box of WIN95/98/ME/NT/2000
is closed, the variables may also be destroyed. If variables are to be
stored and reloaded, the functions #!{...}  #!(...)  #:{...}  #:(...)
may be used. 

The variables use the RAM memory addresses of the so-called Intra
Application Communication Area, ICA (40h:00F0h to 40h:00FFh) for
their storage. If another program also uses these memory addresses,
the variables may fail.
The tests, executed using the variables, were successful on all test
computers (different computer types old and new, DOS and DOS boxes).

Remarks: 
- All results can only be correct, if the value range does never
  exceed -32767...0...+32767.
- Division by 0 is not possible. This division does not perform
  anything.
- The number 0 cannot be negated (-0 and +0 are identical, so they
  are always displayed as +00000).

Creation of return codes (errorlevels)
--------------------------------------
Return codes can be produced at any position of the command line.
If more than one return code are produced, the last one will be
saved and can be evaluated by IF ERRORLEVEL then. Setting a return
code: #R00 to #RFF (hex value causes the code of 0...255).
Setting the return code from the current drive (A=1, B=2 etc): #R\

#,.., Special function: checking for a given drive letter
----------------------------------------------------------------
If a valid drive letter is inserted between the two commas, e.g.
#,d:,  an errorlevel is set, depending on the drive letter.
A: causes errorlevel 1, Z: causes errorlevel 26.
If no valid drive letter is inserted between the two commas, error-
level 0 is generated. Errorlevel 0 is also output in the following
cases:
#,c,   the colon is missing
#,C:   the second comma is missing
#,c:\  this is a directory, not a drive
#, C:, the blank must not exist
#,C:x, undefined x
In batch files may be a line such as  XE :#,%1,
If the first parameter of the command line is D: for example,
%1 will be accepted as a valid drive letter.

Program details
---------------
The XE program was completely written in assembly language.
Upper and lower case letters have the same meaning if used together
with # parameters (#3a is identical to #3A). The program may be dis-
tributed free of charge (freeware). Never distribute the program with-
out its documentation and the enclosed example batch files.

Used memory addresses of the ICA (40h:00F0h to 40h:00FFh):
----------------------------------------------------------
F0 F1  F2 F3    F4 F5 F6 F7 F8 F9 FA FB  FC FD  FE FF
#(rs)  #(tu)                             #:...  #!...
cursur position ------still unused-----  variables

---------------------------------------------------------------------
XE (eXtended Echo) (C) Claussen, Riedwiesenweg 10, D-69181 Leimen,
FREEWARE               claussen.leimen@t-online.de         Germany
---------------------------------------------------------------------
