LM0RM255OF0FD60PL60,60,60TP0BT0WD0OP0UL0FLRHA   page PN


TUTORIAL:  MANIPULATION OF XYWRITE CONTROL CHARACTERS WITH XPL
--------                           ------- ----------
by Robert J. Holmgren; editorial contributions by Joseph Solla
February 1990 (corrected May 1990)

[Plus Addendum for XyWrite 4+, "Coffee Break:  One-Byte, Three-Byte, and Five-Byte Characters", from STACK.DOC for XyWrite 4+ (LastRev.1/18/04)]

Read in XyWrite Expanded Text Mode


   Preface:
   -------
WYSIWYG.  "What You See Is What You Get."  A basic XyWrite tenet.  But on-
screen, there are frequent disparities between the character you see, and the
character you intend, or the character written to text files.  Anyone who's
tried to write a lone guillemet "AE" to the screen, or SEarch for an Escape
character "1B", or hand XyWrite's so-called WYSIWYG text files to demanding
external programs that require pure Ascii code (100% WYSIWYG), knows that
XyWrite falls about 5% short of its proclaimed ideal.  That is, fifteen of
the 255 characters in the Ascii character set are represented on-screen by, &
written to disk with, replacement strings (usually three bytes long) that are
translated when ported to the printer into their originally-intended character
-- but on-screen and in files they remain idiosyncratic, largely undocumented,
and exceedingly difficult to handle.  Unfortunately, these "control
characters" include some of the most important and sensitive characters in the
Ascii set:  the carriage return, Escape, the guillemet characters that
manipulate XyWrite text formatting, a character (Ascii 255) that signals the
presence of functions (XyWrite's basic building blocks), a screen controller
(Ascii 253 "FD") that makes everything *work*, and so forth.  Most importantly,
the control characters intrude at virtually every step of what XyQuest calls
"Advanced User Programming" (and everybody else calls XPL, "EXtended
Programming Language") -- the main subject of this file.

For me, the near-total configurability enabled by XPL is the distinguishing
reason (together with speed) to use XyWrite in preference to other word
processors:  XPL turns XyWrite into an extraordinary power tool.  But the
control characters have many special, complex rules, which can't be treated in
a textbook manner.  They're the dark side of XyWrite, and a genuine pain for
XPL programmers.  This file examines those rules, and suggests means of
manipulating control characters.

If all you really want to do with XPL is make keystroke macros, then
CAPTURE2.PGM or NCAPTURE.PM should fill your needs (these are keystroke
capture utilities, which allow you to repeat sequences of keystrokes; NCAPTURE
is the child of CAPTURE(2) and more flexible: it permits XPL programming to be
hand-crafted or MErged from a disk file into the macro).  But a keystroke
macro isn't programming, it's typing!  This text file is for people who want
to overcome complex, but common, problems in sophisticated XPL programs.
A basic familiarity with XPL and the XyWrite functions is assumed.

The routines in this file are *examples*.  In XPL, there are usually a half
dozen ways to skin the cat.  I've tried to exemplify the main procedures
in one routine or another, somewhere in this file, with emphasis on generic
procedures (ones that work in any III/III+/Nota Bene version) for "public"
programming.

Unfortunately, you're going to have a helluva time printing this file to most
printers.  Don't even try!  But if you *must* try, a printer character set
that replicates the entire Ascii set is required  if it includes all the
control characters, and doesn't crash on chars like Escape, then it *may*
work.  Use a 12-cpi (or smaller) non-proportional font (so the table columns
justify).  Make sure MoDes BO, BU, FU, NM, RV, UL, and 15 (for the importance
of !MD15!, see "3-BYTE FUNCTIONS", below) are established (and differentiated)
in the appropriate PT.  On a Laser printer that obeys Hewlett Packard rules,
set AELM0AFAEOF0AFAEFD60AFAEPL60,60,60AFAEFLAFAETP0AFAEBT0AFAEWD0AFAEOP0AFAEUL0AF at the top of
this file, change AERM255AF to AERM78AF, and use Internal font Medium-Courier
(US-ASCII Symbol Set 10U, *not* Roman-8 Set 8U) -- then run program [a]
against a *COPY* of the present file:

[a]
LB Translate unprintable LaserJet characters Ascii 7-1527, and some other Control Characters  permits *almost* everything to print - NOT a Generic Program  Specific to this file only! 1es 1	cia FF00{0}	cia 07FF07	cia FF07{7}	cia 08FF08	cia FF08FF08	cia 09FF09	cia FF090FF08	cia FF0AFF080	cia 0BFF0B	cia FF0B{11}	cia 0CFF0C	cia FF0C{12}	cia FF0DFB	cia 0EFF0E	cia FF0E{14}	cia 0FFF0F	cia FF0F{15}	cia 1AFF1A	cia FF1A>FF08FEFF08-	cia FF1B	cia FF1B<FF08FEFF08-	cia 7EFF7E	cia AEFFAE	cia AFFFAF	cia FDFFFD	cia FFFF 	cia NMFFAFNMAF	cia BOFFAFBOAF	cia BUFFAFBUAF	cia FUFFAFFUAF	cia RVFFAFRVAF	cia SUFFAFSUAF	cia ULFFAFULAF	cia 10FFAF10AF	cia FFAE4D44AE4D44	se  AERM255	IF@NOT(ER)+++78EIsea  TABLES		se  	UAERM255AFes 0	}PR DoneEX



   Preliminary Set-Up:
   ------------------
Throughout the following discussion, you should keep a window open and handy,
to STore and run fragments of code that you CoPy out of this text.  For
easy identification, all such code fragments terminate with func .

Be sure to disable the Error Help facility, if you use it (set VAEH to 0).
Command:  default eh=0<cr>
(If you're using EH, you probably shouldn't be reading this file!)

To be able to move DeFined strings from the text area to the CoMmand line
during this discussion, CoPy and STore the following PM in a dummy file, and
then load the dummy file onto an ordinary Save/Get key:

[b]
LB Put DeFined text on CoMmand lineSV01=mPV01EX

Apropos of nothing, here's the obverse.  How many times have you
constructed a complex CMline command with painstaking care and wished you
could SAve it for another day?  It's easy:

[c]
LB Insert CoMmand line $tring in text window}GT00EX

Vernon Buerg's LIST.COM (LIST73D.ZIP) is a virtually indispensable tool for
analysis of the problems examined in this text.  Alt-H is LIST's command to
toggle into hexadecimal display, which enables examination of files at the
byte level.  The compact model of LIST (LISTS.COM) will suffice for our
purposes.  You may wish to put the following code on a Save/Get key for
convenience:

[d]
LB LIST the current text window.  Assumption:  LIST.COM resides 
in the current directory, or in the DOS Path SX01,VA$FPdos /c list PV01	EX



   A Few Applications for 3-Byte Strings:
   -------------------------------------
SEarching for control characters in text
SEarching for functions in text
SEarching for formats and MoDes with Ascii-253
Masking certain strings from SE and CHange commands [CH, CI, and CV]
Tricking XyWrite into accepting a 1-byte control character on the CoMmand line
Distinguishing imported *program* files from *text* files
Putting a true CR and/or LF on the command line as a SE or CI argument
Filtering imported text files
Preventing the beep that occurs if you try to use a lone Ascii 174175
   (the guillemets AEAF) in an XPL program
XPL programs that create executing XPL code from non-executing source strings
XPL programs that modify other XPL programs
And lots of other stuff



Terms and Concepts:
------------------
"{Ascii-number}" - a low-order (Ascii 0-31) or high-order (Ascii 128-255)
  character, which often cannot be displayed on-screen in its true form
  by XyWrite, and furthermore is unprintable on many printers,
  e.g. "{Ascii-255}"
"char, character" - the character visually displayed by XyWrite
"CMline" - the CoMmand line (top line of the XyWrite console display)
"PRompt line" - the second line of the XyWrite console display
"XPL" - XyWrite's "eXtended Programming Language"
"n-byte codes" - the actual underlying codes used to signal display of
  particular characters on-screen; the codes which are written in files at
  the DOS-level, or sent to printers, etc.
"string, $" - one or more DOS characters, treated as a sequence


CODES:
-----
one-byte code - XyWrite's visual representation of most 1-byte codes
=============   occupies 1 position in text, 1 position on the CMline,
                and 1 actual byte
    All non-control characters (i.e. most characters) are normally 1-byte
    codes.  The control characters are *also* 1-byte codes, but they vary in
    their adherence to the general rules concerning display stated above -
    read on!

two-byte code - XyWrite's visual representation of the character occupies
=============   only 1 visual position in on-screen text, but 2 actual bytes.
    The only two-byte XyWrite code is the Carriage Return/Line Feed
    combination (Ascii 13/10).  In XPL, the CR/LF combination appears in text
    either as Ascii 13 "0D" or as Ascii 27 "1B"; on the CMline CR/LF appears
    as Ascii 10 "0A" or as Ascii 27 "1B".  See below for examples of
    handling CR/LF in XPL.

three-byte codes - appear in 2 guises, as CHARACTERS and as FUNCTIONS.
================   These three-byte strings are unique to XyWrite.  The first
                   byte of ANY 3-byte code is Ascii-255.
  3-BYTE CHARACTERS:
    XyWrite's visual representation of a 3-byte character occupies only 1
    visual position in on-screen text and 1 visual position on the CMline, but
    3 actual bytes.  XyWrite internally translates them and makes them
    *appear* on-screen as single characters.  When sent to the printer also,
    they are translated into single-byte codes.  Following initial byte
    Ascii-255, the second and third bytes correspond to the *two* characters
    that constitute the displayed source-character's hexadecimal value.
    Thus, the three-byte code for uppercase "A" (hex 41) is "{Ascii-255}41".

    The BASIC PRINCIPLE is that every one-byte character has a corresponding
    three-byte *visual equivalent*, which however is not identical at the
    byte level!  They are displayed the same (they look the same, in BOTH
    Normal and Expanded editing modes) -- but in fact they are different.

    The MOST IMPORTANT DIFFERENCE between 1- and 3-byte character codes is
    felt in XyWrite's treatment of the *control* characters (3-byte codes of
    the *non-control* characters are seldom useful).  One-byte control
    characters are, so to speak, "active" -- that is, they work.  A one-byte
    Ascii-8 (the Back Delete character in DOS) actually performs its DOS
    function, and deletes the immediately preceding character.  True
    Ascii-8s are never displayed on-screen (except by trick -- see below).
    Whereas, in text, the 3-byte Ascii-8 does nothing, and is always visible:
    "08".  Likewise a real 1-byte Ascii-9 (Tab char) performs a tab:
    "	".  In Normal editing mode, you don't see it, though you see it's
    *effect* as it performs a tabular jump; but in Expanded editing mode
    (assuming that AEVATBAF = 0), a 1-byte Ascii-9 appears.  Whereas, a 3-byte
    Ascii-9 is visible at all times and, in text, does nothing:  "09".  These
    examples should not imply that 3-byte characters are "useless" -- far from
    it!  Much of the following text is devoted to their uses.  A concrete use
    in text may be found for the 3-byte tilde Ascii-126 "7E" -- perhaps the
    most frequently-noticed control character, because it belongs to the
    regular Ascii 32-127 character set.  The 1-byte tilde always disappears in
    Normal editing mode, and reappears in Expanded mode:  "~".  Try it:  note
    that the screen contracts in Normal mode!  1-byte tildes are a nuisance,
    except in their rle as soft hyphen markers.  The 3-byte tilde "7E" is
    usually the one to use in text.  It displays and also prints properly --
    but if you export it to a non-XyWrite program in file form, it will make
    no sense.  Thus, there are advantages and disadvantages to the use of
    3-byte characters.

  3-BYTE FUNCTIONS:
    XyWrite functions occupy 3 visual positions in on-screen text (functions
    cannot be displayed on or moved to the CoMmand line).  XyWrite internally
    translates them and makes them *appear* on-screen as MDBOboldMDNM
    three-character mnemonic function *names*.  These function names have no
    relationship whatsoever to the underlying 3-byte string that constitutes
    the function.  Thus, the underlying 3-byte code for function is
    "{Ascii-255}", but on-screen it appears as "".  N.B.:  It's not
    well-known that, sent to the printer, functions are translated, as e.g.
    "AEMD15AFBC AEMDNMAF".  If MoDe 15 is defined as a Bold font or a Shadow
    attribute in your .PRiNter file's applicable PT table(s) -- e.g.
    "MD 15+MEDIUM-COURIER-BOLD" -- then functions will print in a manner
    that replicates their on-screen appearance!

    Following initial byte Ascii-255, the second byte of a function is either
    "", "", or "" (Ascii 128129130), and the third byte is an
    odd-numbered Ascii character (Ascii 1, 3, 5, 7, etc).  To obtain any
    3-byte character in the Ascii set, see "Syntax of three-byte CHARACTER
    sequences", as well as routines [fff] and [ggg], below.


five-byte codes - XyWrite's visual representation of a five-byte code
===============   occupies 3 positions in text, 5 positions on the CMline, and
                  5 actual bytes.
    The first three bytes in *any* 5-byte string are the three-byte code for
    Ascii-255, i.e. "{Ascii-255}FF".  On-screen, "{Ascii-255}FF" *appears
    like* a space:  "FF".  Five-byte codes are almost exclusively for use in
    XPL; sent to the printer, they mean nothing.

  5-BYTE CHARACTERS:
    The fourth and fifth bytes represent the Ascii equivalent of the
    hexadecimal value of the three-byte Ascii character.  Thus, the five-byte
    SEArch-string for three-byte "A" (Hex 41) is "{Ascii-255}FF41".

  5-BYTE FUNCTIONS:
    The fourth byte is either "", "", or "" (Ascii 128129130),
    and the fifth byte is an odd-numbered Ascii character (Ascii 1, 3, 5, 7,
    etc).  Unique combinations of these characters create the XyWrite
    functions.

  The MOST IMPORTANT USE of 5-byte codes is to enable you to SEArch (in XPL)
  for *three-byte* codes (including functions).  Thus, the SEArch-string for
  func is "{Ascii-255}FF" because func is the three-byte code
  "{Ascii-255}".  On-screen in XyWrite, this five-byte code will appear as
  "FF", NOT as .  Examples appear below.



Syntax of three-byte CHARACTER strings:
--------------------------------------
Example:  A 3-byte upper case "A" (Hexadecimal 41Ascii 65)

The first byte of any three-byte string ($) is *always* Hex FF = Ascii 255
The second and third bytes of the string correspond to the *two* characters
  that constitute the displayed source-character's hexadecimal value.
In other words, the 3-byte $ for "A" (Hex 41) is "{Ascii-255}41"
                the 3-byte $ for "B" (Hex 42) is "{Ascii-255}42"
                the 3-byte $ for "C" (Hex 43) is "{Ascii-255}43"
                the 3-byte $ for "AE" (Hex AE) is "{Ascii-255}AE"
                the 3-byte $ for "AF" (Hex AF) is "{Ascii-255}AF"
and so forth.  In a true WYSIWYG display (e.g. LIST.COM), "{Ascii-255}41"
would look like " 41".  But XyWrite displays it as "A".

Compare these columns with LIST.COM:

bytes
1  3

A  41
B  42
C  43

A table of the "character set" expressed entirely in 3-byte codes, which
comes in handy in XPL, appears at the end of this text.



Several important XyWrite *rules* to remember are:

  if you load a three-byte character code in your KeyBoarD [filename.KBD]
  file, XyWrite interprets it as a *one*-byte code when you strike that key
  during normal text entry.

  if you *move* a three-byte character code from the text area onto the
  Command Line, it is transformed into a one-byte code (for purposes of
  SEarches, CHanges, etc).  Interesting trick:  you can move three-byte chars
  from the text window to the CMline and then, as one-byte chars, back into
  the text window, using routines [b] and [c] above (sometimes, e.g. Ascii-8
  [BackDelete], you must precede the character with a three-byte Ascii-255,
  for this to work).

  functions - , usually assigned in XyWrite .KeyBoarD files to
  Alt-Ctrl-keypad_keys 0 through 9, generate 1-byte characters in text for
  *all* non-control characters, and 3-byte forms for *all* control characters
  N.B.  When using - , it is necessary to depress and *hold down* the
  Alt-Ctrl keys until all numbers of the Ascii code are entered -- then
  release Alt-Ctrl, and the code will appear on-screen.

A major source of confusion in all this is that XyWrite is writing code in
Hexadecimal, and interpreting Binary strings in Hexadecimal notation, but
telling *you* to think and work in Ascii.  Moreover, XyQuest is not very
forthcoming about these issues, even when they appear right on the surface
(as in VAriable AEVA$FSAF).  This necessitates a lot of mental Ascii-Hex
translation.  It's a good idea to have tables, such as those at the end of
this file.  Put them in your HeLP file for ready reference.  Simple programs
like [e] and [f] can be useful also:

[e]
LB Get Hex value of any decimal value  works in any XyWrite IIINota Bene version SV01,	
SV02,SV03,SV05,0123456789 Get Hex value.  Input decimal [Ascii] value of char:  LBAPR <cr>XC to end; `Esc' abortsSX04,RCIFIS04==IS02LBB}PR AbortEXEIIFIS04IS01>-1GLCEIIFIS04IS05>-1PV04SX03,IS03+IS04EIIF@SIZ(IS03)<3GLAEILBCIF@SIZ(IS03)<1 No valueGLBEIIFPV03>255 Bad value: PV03GLBEISU01,SX02,0LBDIFPV03>15SX03,PV03-16SX02,PV02+1GLDEIGT01SU01,IFPV02<10EXEIIFPV02<11SV02,AEXEIIFPV02<12SV02,BEXEIIFPV02<13SV02,CEXEIIFPV02<14SV02,DEXEIIFPV02<15SV02,EEXEISV02,FGT01 Hex PV02SX02,PV03GT01PV02PR DoneEX

[f]
LB Get decimal value of any Hex value  works in any XyWrite IIINota Bene version SV01,0123456789ABCDEFSV02,SV03, Get decimal value.  Input Hex value of char:  LBAPR <cr>XC to end; `Esc' abortsSX04,@UPR(RC)IFIS04==IS02LBB}PR AbortEXEIIFIS04IS01<0GLAEIIF@SIZ(IS03)<1PV04SX03,IS04GLAEISX02,IS03IS01*16+IS04IS01 Decimal PV02PR DoneEX


                       ͻ
͹ PROGRAMMING EXAMPLES  
                       ͼ

THREE-BYTE CODES AND THE .KeyBoarD [.KBD] FILE:
==============================================

How can you enter three-byte codes directly, input real-time on the keyboard,
without using XPL programming techniques?  There are two reliable
methods (A, B) and one UNreliable method (C).  First, CAll your .KBD file and
select an empty key.  Remove the Ascii 0 usually installed on empty keys (it
looks like a space but it's actually a 3-byte Ascii 0), then use one of the
following methods (example:  enter a 3-byte "A"=Hexadecimal 41=Ascii 65 into
text):


A) Unique method (make a *specific* character, e.g. a 3-byte "A"):

[key#]=NO,{3-byte Ascii-255},4,1
    which *looks* like:
[key#]=NO,FF,4,1

A leading "NO" No-Operation function is required because keyboard assignments
of more than one character *must* begin with a function.


B) Generic method (make any character):  This does for Hex what the - 
functions do for decimal.  Assuming that functions - are assigned to
their default positions in the .KBD file (Alt-Ctrl-keypad_keys 0 through 9),
place a 3-byte Ascii-255 *by itself* on a blank key in the .KBD file with
Alt-Ctrl-keypad_255.  The result *looks* like:

[key#]=FF1B                                                                

When you hit this key during text entry, a 1-byte Ascii-255 is generated.
To make a three-character "A" (Hex 41), first hit this new Ascii-255 key.
Note that *nothing happens* on-screen!  This is because XyWrite is waiting for
two more characters, with which to form a 3-byte code.
    RULE:  Ascii-255 *always* signals the beginning of a 3-byte code!
So type the number "4", then the number "1". Now an "A" appears!  If you want
a 5-byte code for "A", type "FF41" immediately after hitting your new
Ascii-255 key.  Case is significant!


C) For Control Characters *ONLY*, there is also the traditional, documented
- method, which however has the unsettling peculiarity that the
character is not displayed on-screen until you physically release the Alt-Ctrl
keys.

Example:  put a tilde "7E"=Ascii 126=Hex 7E in text:

[key#]=R1,R2,R6

Try the keyboard assignment above, and note the response of the screen and
keyboard as you strike the assigned key (don't release it immediately).  Then
compare the *immediate* response obtained with the following assignment:

[key#]=NO,{3-byte Ascii-255},7,E

With non-Control Characters, the - method puts a 1-byte character in
text.  In short, - is an unreliable method for inserting 3-byte
character codes, and should be put to pasture.



HANDLING THE CONTROL CHARACTERS:
===============================

Primary Search Methods:
======================

In general, there are three (3) methods of SEarching for a CHARACTER,
and one (1) method of SEarching for a FUNCTION:

MethodAppears on CMline Underlying SEarch$  LenFound $tring    Len
----------------------- ------------------  ---------------    ---
1-bytesea /A/	     "A"                  1 1-byte "A"       1
3-bytesea /41/	     "{Ascii-255}41"      3 1-byte "A"       1
5-bytesea /FF41/	   "{Ascii-255}FF41"    5 3-byte "41"       3
5-bytesea /FFM/	   "{Ascii-255}FFM"    5 3-byte func M  3

How do these differ?  The "one-byte method" is the ordinary method we use in
everyday editing; in the example above, se /A/	puts a genuine one-byte
"A" (Ascii 65Hex 41) on the CMline, and it flags one-byte "A"s.  The other
two methods are mainly for use in XPL, and represent useful tricks.

The "three-byte method" successfully searches for one-byte strings --
because the *rule* is -- A VERY IMPORTANT RULE! -- that a three-byte string
is transformed into a one-byte string when placed on the CM line.  Note that
the .KBD file does this also, with such characters as Escape and the
guillemets:  they appear as three-byte characters in the .KeyBoarD file,
but are placed in text by the .KBD file as one-byte characters.
*HOWEVER*, a three-byte *SEArch* string will NOT flag itself, nor any
other three-byte *text* string!  Suppose this is the PM:

[g]
LB AESV01AF is a three-byte "41", whereas this is a one-byte "A" SV01,41sea /PV01/	EX

If you run the PM above upon itself (in a separate window), you'll find that
only the one-byte "A" is successfully SEArched.

Similarly, the "five-byte method" finds three-byte strings without flagging
either the five-byte command string (i.e. SEarch string "FF41" will NOT flag
itself) or the genuine one-byte "A".  This works because the 3-byte
Ascii-255 that begins the 5-byte command string is transformed on the CMline
into a one-byte Ascii-255, which is followed by non-control characters "41"
 -- and thus becomes the equivalent of a three-byte "41":

[h]
LB AESV01AF is a five-byte A "FF41", whereas this is a three-byte "41", and 
this is a one-byte "A" SV01,FF41sea /PV01/	EX

The main use of five-byte strings is to SEArch for, or else represent,
functions.  Again, note that SEarch string "FF" will NOT flag itself, but
only genuine function .  Execute this code:

[i]
LB AESV01AF is a five-byte function : "FF" SV01,FFsea /PV01/	PR Hit XC againEX

The three-byte codes are extremely useful, especially when you are executing
an XPL program that creates or modifies another XPL program located in the
text window (or if you execute an XPL program against itself).  Thus, for
example, the following code flags the presence of three-byte codes within a
text (this would allow you to determine whether or not the text window
contains an XPL program -- run the following PM against itself as a test):

[j]
LB SEArch for {Ascii-255}, which is located between the "" separators -- version for XyWrite v3.54+ ONLY! -- skip past three-byte spaces and dashes often used to inhibit word-wrap in normal textSV01,202D=LBAse FF 	IFER}PR DoneEXEIk[kSV02=IFIS02IS01>-1cGLAEI Control character Ascii-255 located here}PR Hit a key to continueSX02,RCcGLA



Control Character Search Methods:
================================

XyWrite's "control characters" are:

                            *Usually*         SEarch Methods 
                   Ascii    Appears            listed below  
Char  Hex          (Dec)    As {1-3 bytes}    Editing 1B1A XPL 
----  ---          -----    --------------    =======----=== 
      00              0     suppressed        NA         NA  
08     08     BS       8     BackSpace {1}     NA         3   
09     09     Tab      9     tab or 09 {1}      1          23 
0A     0A     LF      10     0A {1}             NA         3   
0D     0D     CR      13     1B {2}             1          29 
0D0A    0D/0A  CR/LF   13/10  1B {2}             4          95 
     10             16      {1}             NA         6   
11     11             17     11 {3}             7          8   
1A     1A     EOF     26     not seen {1}      NA         NA  
1B     1B     Esc     27      {1}             1          1   
      20     Spc     32     a space {1}       1          12 
7E     7E            126     7E {1}             1          12 
AE     AE            174     AE {1}             1          12 
AF     AF            175     AF {1}             1          12 
FD     FD            253     FD {3}             7          8   
      FF            255     not seen {1}      NA         3   

**********************************************************************

SEarch Method #1:
----------------
  SEarch for a character while editing by keying the character from the
  KeyBoarD:  e.g. to SEarch for Escape, hit the Escape key to put the Escape
  character (as recognized by XyWrite, i.e. it looks like Ascii-16) on the
  CM line within a "se  ", "se ", etc., context.

  Do the same thing in XPL:

[k]
se 	EXHere's a 1-byte Escape: ""
  or
[l]
se  	EXHere's a 1-byte Escape: ""

  The following coding of the .KeyBoarD file is assumed (use *3-byte codes*
  for the control characters!):

    ESCape key:
1=1B

    Tab key:
15=09

    Enter key (the CR/LF or Ascii 13/10 combination):
28=0D
    plus, for 104-key keyboards:
104=0D
    and on TABLE=CTRL (to enable easy CMline SEarches for "Enter" or CR/LF):
28=0A

    Tilde (this is "NO,{Ascii-255},7,E"):
41=NO,FF,7,E

    Guillemets Ascii 174175 -- these should appear in the KBD file as
    *3-character* codes, i.e., Ascii_255-A-E and Ascii_255-A-F.  An important
    fact-of-XyWrite is that 3-char codes in the KBD are transformed into
    1-char codes when placed in text.  Copy them from this file, or insert
    them in the keyboard file by *keying* and , usually
    mapped as Alt-Ctrl_1-7-4 and Alt-Ctrl_1-7-5; an appropriate assignment for
    these codes is Ctrl-< and Ctrl->:
51=AE
52=AF

**********************************************************************

SEarch Method #2:
----------------
  SEarch for a character in XPL by using a 3-byte SEarch code.
  E.g., a 3-byte Tab:

[m]
se  09	EXHere's a 1-byte Tab: "	"
  or
[n]
se 20	EXHere's a 1-byte space: " "

**********************************************************************

SEarch Method #3:
----------------

Trick XyWrite into accepting a 1-byte control character on the CoMmand line,
by prefixing a 3-byte Ascii-0 to the SEarch character.  Such tricks are
unnecessary for most control characters, because simpler methods are
available; but for Ascii 8 and 10 especially, this is a good method.  Note
that separators are *necessary* for this method to work (here, we use
Ascii 6 "" because it does not occur in the code of any function); a space
separator ("se  AEPV02AF33+	") fails.  AESU01AF is a *demo* routine.

[o]
LB This routine will find the following 1-byte characters: Ascii 8910253 (flags screen MoDes BU then NM)a function (NO ) that contains, as its first byte, Ascii 255:   	 
 
 SU01,se PV0233+	SV02,FFGT01[PR Found 8 - Hit a keySX02,RCSV02,FF	GT01[PR Found 9 - Hit a keySX02,RCSV02,FF
GT01[PR Found 10 - Hit a keySX02,RCSV02,FF0DGT01[PR Found 13 - Hit a keySX02,RCSV02,FFFDGT01PR Found 253 MDBU - Hit a keySX02,RC	PR Found 253 MDNM - Hit a keySX02,RCLB Next, get Ascii-255: SV02,FFFFGT01[PR Found 255 - DONE!EX
  MDBU1-byte Ascii-253 ("FD") flags MoDed text!MDNM 


Note in [o] that Ascii 253 controls MoDed text *display*.  The display must be
switched *on* (Normal, not Expanded, edit mode)!  Buried in the code are
strings that control the screen display in Normal mode; they're ignored in
Expanded mode.  These are the (undocumented) 6-character SEarch strings
(expressed in 3-byte codes) that display the various MoDes (actually, only the
first 4 characters are necessary, but here's the 6-char code anyway):

BO:  FD0381DD02AF
BU:  FD0381E002AF
DB:  FD0381ED02AF
DD:  FD0381F302AF
DL:  FD0381F002AF
DN:  FD0381EC02AF
DR:  FD0381EF02AF
DS:  FD0381F202AF
DU:  FD0381EE02AF
DV:  FD0381F102AF
FL:  FD0381F402AF
FN:  FD0381F902AF
FR:  FD0381F602AF
FU:  FD0381F502AF
IB:  FD0381E502AF
ID:  FD0381EB02AF
IL:  FD0381DC02AF
IN:  FD0381E402AF
IR:  FD0381E702AF
IS:  FD0381EA02AF
IU:  FD0381E602AF
IV:  FD0381E902AF
MM:  FD0381FA02AF
NM:  FD0381DC02AF
RV:  FD0381DF02AF
SB:  FD0381F802AF
SD:  FD0381E302AF
SO:  FD0381F702AF
SU:  FD0381E202AF
UL:  FD0381DE02AF
1:   FD03810102AF
2:   FD03810202AF
3:   FD03810302AF
4:   FD03810402AF  and so forth for numeric modes -- just insert the
Character Ascii 1, 2, 3, 4, etc., as the fourth char in the string.

What can you do with this list?  First, note that, in Normal editing mode, if
you try to SEarch for !MDBO!, the search fails, whereas in Expanded mode it
succeeds (try it!).  But using the listed SEarch string, you will flag !MDBO!
in Normal mode.  The SEarch string "FD038102AF" will find *any* MoDe.

Format codes like AEOF1AF are also written to the screen in Normal editing mode
with deeply-embedded strings, which can nevertheless be *SEarched* (in Normal
edit mode only)!  How are these codes constructed?  Examine a relatively
simple format like LM Left Margin (which accepts only a single value):

Byte#  Char  Examples:  AELM1AF ("FD10020A00") and AELM3.9AF ("FD10'00AF")
-----  ----  --------------------------------------
  1     FD    Ascii 253 (FDh)is the 1st byte of ALL formats and MoDes
  2     10    Ascii 16 (10h) is the UNIQUE IDENTIFIER of format "LM"
  3     Generally, byte 3 can be ignored () but NOT skipped in SEarch$
        The important thing is to get bytes 1, 2, 4, and 5 precisely!
AELM1AFĿ
 3     02    Low-order Ascii 2 (02h) if bytes 4 + 5 = a WHOLE 8-bit number 
             which limits total string length to 5 bytes                  
           Bytes 4 and 5 form a 16-bit string that represents value of LM 
           ALL VALUES include one digit to the right of the decimal point 
 4     0A    no. of 1's   (Ascii 10 = 0Ah  1.0)                           
 5     {0}  no. of 256's (Ascii 0 = 00h)                                  
AELM3.9AF͵
 3         Ascii 130 (82h), the high-order complement of Ascii 2 (02h),  
             used if a 16-bit value is required, and/or the decimal point 
             is significant                                               
  4    '    no. of 1's   (Ascii 39 = 27h  3.9)                           
  5    {0}  no. of 256's (Ascii 0 = 00h)                                  
           Byte 6 = number of "extra" bytes in the string                 
           ALL VALUES include one digit to the right of the decimal point 
  6        Ascii 2 (02h) = 2 "extra" bytes (6 and 7) - ignore them       
  7    AF    Ascii 175 (AFh) = terminator (ignore)                         


Left Margin is a poor choice to example, because it contains a problematic
character, Ascii 16 "", which can't be SEarched on the CM line.  To show
how to SEarch for formats, lets take a different, also simple format like
AEOF1AF, which on-screen (in Normal edit mode) has the underlying character
string "FDH020A{0}".  Compare AEOF2AF = "FDH0214{0}"; AEOF5AF = "FDH0232{0}"; AEOF4.9AF =
"FDH041{0}{0}{0}".  Different rules than LM!  Yet the important thing here
remains to get bytes 1, 2, 4, and 5 -- for *most formats* with only one
numeric value, these form a significant, unambiguous SEarch string (the
trailing characters, bytes 6+, can be ignored).  For OF0, char 4 is Ascii 0;
OF1 = Ascii 10; OF5 = Ascii 50; and for OF4.9 the fourth char is Ascii 49.
Simple, eh?  A mess!  Too complex to examine further here; I barely understand
it myself.  Moreover, an XPL SEarch instruction has to be *very* carefully
crafted, with attention to getting control characters on the CMline
successfully before eXeCuting:  e.g., to find AEOF1AF:

[p]
SV01,FD48FF0A sea  PV01+[+	[PR Found OF1 - DoneEX
>OF1<

Several problems with these routines:  First, the CM line won't SEarch an
Ascii-0 or an Ascii-16.  A *terminating* Ascii-0 in a string is no problem;
just omit it, you have enough chars for a precise and significant SEarch.
But if you're looking for AEOF0AF, you've got trouble!  The best you can do is
SEarch for *any* OF format, using the first three chars of the search string:
"FD4802" -- that nails OF, but without a value.  Ascii 16 is only a problem with
a format like AELM1AF, because the SEarch string is "FD10020A00" (the last char
is Ascii-0).  Here, the best you can do is SEarch for "FD020A", which
will flag AELM1AF (but possibly other formats as well).  BTW, do NOT use
separators in the SEarch string!  You can lose all Save/Gets in memory, if you
happen to mate the wrong combination of separator characters + SEarch string
characters.  Also, SEarches like these seem to jog memory to the edge of a
breakdown, and you need to get your cursor off the found format, and
preferably back up to the CMline, immediately, before calling any other
variables in memory.  Obviously, XyWrite's designers didn't anticipate that
we'd be monkeying with the screen controllers, and there are no safeguards in
this area.  (Nor, I think, can we legitimately claim there's a "bug"!)

These are the *unique identifiers* (byte 2) for some of the more important
formats:

AL=FD06       FN1=FD      LL=FD09       PT=FD04       WD=FD60
AP=FD4C       FN2=FD      LM=FD10       RM=FD12       WS=FDc
BF=FDG       FN3=FD      LR=FD02       RT=FDD
BK=FD^       FR=FD.0102     LS=FDM       SC=FD0F
BT=FD[       FT=FDE       NI=FD94       SD=FDO
FC=FD.0101     HM=FD]       NJ=FD08       TB=FDa
FD=FDS       HY=FD01       OF=FDH       TP=FDQ
FF=FD_       IP=FD14       OP=FDb       TS=FD18
FL=FD.01      JU=FD        PL=FDU       UL=FD05

Suffice to say, a "peek-at-memory" or zapper utility (e.g. MEMWALK) will
display the screen controllers for any desired format.  With some tinkering,
you can develop suitable SEarch routines for most formats.  And it *may* be
worthwhile, because in Normal editing mode, you can't search for AEOF1AF
outright, whereas the screen controller strings flag it every time.

**********************************************************************

SEarch Method #4:
----------------

SEarch for the CR/LF combination when editing.  Load a 3-byte Ascii 10 on a
key, e.g. the Enter key in TABLE=CTRL:

28=0A

Then go to the CoMmand line and command:  "se  {Ctrl-Enter}<cr>"

The CMline *looks* like:

"se  1B"   Hit Enter	to eXeCute.

**********************************************************************

SEarch Method #5:
----------------

SEarch for the CR/LF combination in XPL (use a 3-byte Ascii 10 "0A"):

[q]
se  0A	EX

**********************************************************************

SEarch Method #6:
----------------
SEarch for a *true* 1-byte Ascii 16.  The fact is, there's no way I know of to
SEarch for a true Ascii 16 from the CM line.  Ascii 16 is the *only*
character that can't be SEarched from the CMline, period.  Routine [r]
is a time-consuming kludge, but it works.  It DeFines 5000 bytes of a file at
a time, from beginning to file-end, and checks whether Ascii 16 is contained
within each 5000 byte text-chunk; if found, it replaces "" with "{16}" and
continues SEarching to end-file.  In XyWrite v3.53-, you *must* use an
ordinary Save/Get 0-9A-Z, e.g. AESVAAF instead of AESV04AF and AEISAAF instead of
AEIS04AF:

[r]
SX01,5000SV02,SU03,jmp PV01	LBAkGT03kSV04SX05,IS02IS04IFPV05>-1SX01,PV01-5000+PV05GT03{16}SX01,CPGLBEISX06,CPIFPV01==PV06LBBSX01,PV01+5000GLAEIEX

**********************************************************************

SEarch Method #7:
----------------

While editing, SEarch for 3-byte control character codes using
functions - .  E.g. Ascii 253, "FD"

Go to the CoMmand line, and enter:  "se  <cr	>"

With default keyboards which map funcs - to Alt-Ctrl, this means that
you go to the CoMmand line and key "se  {Alt-Ctrl-keypad_2-5-3}", then hit
Enter	

**********************************************************************

SEarch Method #8:
----------------

SEarch for 3-byte codes in XPL.
E.g., "FD" (use a 5-byte Ascii 253 SEarch string):

[s]
se  FFFD	EXHere's a 3-byte Ascii 253Hex FD: "FD"

**********************************************************************

SEarch Method #9:
----------------
This trick gets the true CR/LF string "0D0A" onto the CM line (not as "1B"
or "FF0DFF0A", but as "0D0A").  There are 3 benefits:  first, you can
successfully issue a command like "cia20/{0D0A}/0D0A/" without having the
command eXeCute prematurely because XyWrite interprets it as
"cia /{0D0A}/1B/" where the "1B" is a <cr> or eXeCute command, with the
undesired result that the first half ("{0D0A}") of the search/replace string
is inserted in text; second, you can SEarch for the CR/LF combo without also
flagging a lone Ascii 10 and/or Ascii 13 into the bargain; third, no "Missing
separator" error is generated.  N.B.  *Copy* the code below FROM THIS FILE
(you won't be able to construct the following code with plain-vanilla
XyWrite! -- examine it with LIST.COM, to see what it really is):

[t]
sea FF
 FF0A[[++[+	[PR 13/10 combo is here!EX


   or

[u]
cia {0D0A}FF
 FF0A[[++[+	EX

Suppose, for example, you want to delete lone Ascii 13s and/or 10s from an
imported text file, without deleting the carriage return/line feed 13/10
combos that XyWrite recognizes as a paragraph terminator.  In addition to the
"{Ascii-255}0A" and "{Ascii-255}0D" trick exampled in [o] above, you will see
if you LIST the following code that all the three "1B"s in the code are
*lone* Ascii 13s (hex 0D) rather than the 13/10 combos that they appear to be:

[v]
cia FF
 FF0A[[++[+ccc{0D0A}	cia FF0A[[[+	cia FF
[[[+	cia {0D0A}FF
 FF0A[[++[+	EX

Now, suppose you import a file that contains lone 10s, 13s, or reversed 13/10
combos (i.e. 10/13 "0A0D" instead of 13/10 "0D0A").  Let's regularize them
all, i.e. make them all 13/10.  XyQuest wrote a special FIXCR.EXE file to
handle this "problem".  In fact, XyWrite itself handles the matter very
competently and quickly (makes you wonder, doesn't it?):

[w]
LB
Convert all good Ascii 13/10s to one of 128 (!) *undocumented* 3-byte screen
representations of "1B"; here we arbitrarily use "{Ascii-255}(r".  This is
entirely unnecessary - you could use any dummy string to hold the 13/10s,
such as "{0D0A}" -- but I use "{Ascii-255}(r" as an excuse to mention these
"hidden" char sets, which nobody talks about.  They're a can of worms into
which we won't delve here, beyond remarking that EVERY character has 128
undocumented 3-byte forms  I quote my teacher, the great Indonesian
cyberguru Ir. M. O. Parlindungan, who invariably answers my bewilderment with
a cryptic, "You figure it out, Sonny Boy!"
cia FF
 FF0A[[++[+cccFF(r	LB Convert reversed <cr> Ascii 10/13 to undocumented "1B"cia FF0A FF
[[++[+cccFF(r	LB Convert Ascii 10 to undocumented "1B"cia FF0A[[+ccFF(r	LB Convert Ascii 13 to undocumented "1B"cia FF
[[+ccFF(r	LB Restore undocumented "1B" to Ascii 13/10cia FF(rFF
 FF0A[[++[+	}EX

Try it out on this test prose (Ascii 10, 13, 10/13 and 13/10 intermixed)
(view in Expanded text mode):

------------------------------------------------------------------------
The following character is an Ascii 13>
The following character is an Ascii 10>
The following combo is a reversed <cr>, an Ascii 10/13>

The following combo is an orthodox XyWrite <cr>, an Ascii 13/10>
------------------------------------------------------------------------



ERROR-HANDLING WITH CONTROL CHARACTERS:
======================================

Guillemets:
==========

Prevent the beep that occurs if you try -- as, for a variety of reasons,
you might be tempted -- to use a lone Ascii 174 or 175 (the "AEAF"
guillemets) in an XPL PrograM.  An "Invalid formatting character" or
(sometimes) "Missing separator" error results (due to unmatched guillemets).
The following PM demonstrates how to convert a three-byte guillemet to a
one-byte guillemet, and then back to three-bytes again, within XPL.  Run this
"interactive" PM upon itself in a separate window (the error beep is
suppressed):

[x]
LB
   Demo on handling 3-byte and 1-byte guillemets in SEarches
=SX02,VA$EBdefault eb=0,0	LB 
   A 3-byte guillemet is located between the "" separators:
se AE  SEarch skips the "AE" strings!  (Hit any key to continue)LBA	IF@NOT(ER)PR Flagged: 1-byte guillemetSX01,RCGLAEI No "Invalid formatting char" errors in Normal edit mode...SX01,RCLB
   Replace the 3-byte guillemet SEarch string with a one-byte guillemet,
   using 5- and 3-byte Change Invisible Absolute strings between the ""
   separators.  Errors occur in Normal editing mode!:
cia FFAEAE	cia FFAEAE  Change the 3-byte "AE" to 1-byte "AE"SX01,RCLB
   A 3-byte guillemet is located between the "" separators:
se AE   Note that "AE" strings are now flagged also!LBB	IF@NOT(ER)PR Flagged: 1-byte guillemetSX01,RCGLBEI And "Invalid formatting char" errors occur in Normal edit mode!SX01,RCLB
   Restore the 3-byte guillemet SEarch string, using 3- and 5-byte Change
   Invisible Absolute strings between the "" separators.  No more errors!:
cia |AE|FFAE|  Restore the 3-byte SEarch strings only...	SX01,RC Again inhibits "Invalid formatting char" errors in Normal edit mode...SX01,RCdefault eb=PV02	}PR DoneEX



Get Lone Guillemets onto Individual Save/Gets:
=============================================

Getting lone guillemets onto Save/Gets is a major programming headache, which
often prevents us from doing everything we want to do.  There are several
solutions to the problem.  One which I used for several years is exampled in
routine [y]:

[y]
SX01,VAWBd wb<FFAE	SX02,VAWBd wb<FFAF	SX03,VAWBd wb<PV01	EX

The strings "FFAE" and "FFAF" above are five-byte codes (e.g.
"{Ascii-255}FFAE").  Routine [z] is equivalent to [y], but prolix:

[z]
SX01,VAWBdefault wb<	SX02,VAWBdefault wb<	SX03,VAWBdefault wb<PV01	EX

Both [y] and [z] above put Ascii 174 and 175 *individually* on Save/Gets
02 and 03, respectively.  They temporarily grab the Window Borders VAriable
and use it to hold a string of characters that XyWrite transforms into genuine
one-byte guillemets (the "active" guillemets that really work, as opposed to
the passive 3-byte guillemets that do nothing but are so useful in XPL
SEarches, etc).  VAriables WB Window Borders and RL RuLer are anomalies among
the XyWrite *numeric* VAriables, because they accept as arguments *prose*
strings of varying maximum lengths (VAWB=6 chars, VARL=11 chars), and use
the unusual operator "<" to enter the argument.  Note that the original value
of the VAriable is restored before these routines terminate.

A different solution, which has interesting ramifications far beyond this
particular problem, does not tamper with VAriables, runs faster, and moreover
is compatible back to early versions of XyWrite (v3.15 at least), is [aa]:

[aa]
SU01,SX00,IS00AEGT01SX02,IS00AFGT01SX03,IS00EX

Routine [aa] puts the guillemets (in three-byte form) on the CMline one at a
time, and then in effect "shells" from the main program into a SUbroutine that
reads the CMline string (now transformed into 1-byte Ascii 174 or 175) as an
initial argument, aka AESV00AF.  QED.

In version 3.54, the parsing command "XS" was introduced; it was further
enhanced in version 3.55 with a capacity to use wildcard separators.  This
enables a new and even faster method of getting lone guillemets on individual
S/Gs.  Unfortunately, it is not downwardly compatible.  [bb] is the basic
v3.54+ method:

[bb]
SV01,ASV02,AXS01,02,03,04,05 Results: lone guillemets on PV03 "PV03" and PV05 "PV05"; separator on PV04 "PV04"EX

Regrettably, [bb] will not *directly* extract Ascii-255 to AESV04AF in this
fashion:  ...AESV01,AE{3-byte 255}AFAFAESV02,{3-byte 255}AF... because the length
of result separator AESV04AF is 3 bytes (as you'd expect), not 1 byte -- and you
can't use a 1-byte 255 as source separator AESV02AF without error.  See,
however, [ff] and [gg] below, for two-stage XS parsing routines that succeed.

The following method is only available with v3.55+ ("X" in AESV02AF is the
wildcard for "any character"):

[cc]
SV01,SV02,XXS01,02,03,04,05 Results: lone guillemets on PV04 "PV04" and PV05 "PV05"; PV03 is empty "PV03"EX



Get Ascii-255 onto a Save/Get:
=============================

Ascii 255 can be handled in the same manner as the individual guillemets in
routines [y], [z], and [aa] above -- e.g., in routine [dd] below, a 3-byte
Ascii-255 occurs after :

[dd]
SU01,SX00,IS00FFGT01SX04,IS00EX

The potential *use* of Ascii-255 in the resulting form, as AESV04AF in [dd]
above, is essentially limited to string concatenation, as in [ee], which
creates a function, and inserts that function in text at the Bottom of the
Form (M) -- in [ee], we make the one function XyQuest deems so "dangerous"
that it won't permit it to be created with func - keys:  Toggle
Scroll_Lock, , which consists of the 3-byte string "{Ascii-255}":

[ee]
SU01,SX00,IS00FFGT01SX04,IS00SV05,SX06,IS04+IS05 MGT06EX

Functions are good source-strings to obtain Ascii-255.  In routine [ff], we
obtain 255 from func ("{Ascii-255}"); all three of the most potent
command characters (Ascii 174175255) are extracted very quickly by this
method (but it works in v3.54+ ONLY):

[ff]
SV01,SV02,XS01,02,05,06,04SV01,XS01,02,03,06,04 Results: lone guillemets on PV03 "PV03" and PV04 "PV04"; Ascii-255 on PV05 "PV05"EX

[gg] is a variant on routines [bb] and [ff].  It parses a 3-byte Ascii-255 to
get a 1-byte Ascii-255, using the second byte of the 3-byte 255 ("F") as a
separator:

[gg]
SV01,FFSV02,FFXS01,02,03,04,05SV02,FXS04,02,06,07,08SX08,@SIZ(IS06) Results: guillemets on PV03 "PV03" and PV05 "PV05"; 255 on PV06, byte-length="PV08"M0D0DProof that Ascii-255 is on AESV06AF:0DA AEGT06AF string literal melds with "41" to make a 3-byte "A":  >41<[[[GT06EX

Notice, in routine [ff] above, that Ascii-255 won't display on the CMline.
Ascii 255 never can be displayed alone in XyWrite; it is a *combinant*
character, with extraordinary binding strength.  On the CMline it is neutral
(simply doesn't appear); but if you put Ascii-255 in text, it immediately
attracts the two characters situated to its right, and attempts to meld into a
function or other three-byte string.  Uncontrolled, a lone Ascii-255 inserted
into text -- or, worse, into XPL programming code -- may turn that textcode
into faulty gibberish or crash your whole XyWrite system.  Here, we insert an
Ascii-255 between funcs ("{Ascii-255}") and , to see the effect:

[hh]
SU01,SX02,IS00FFGT01 se  FF	GT02EX

So, now that we've got Ascii-255, what can we do with it that's
constructive?  Here's an example.  Since *is* indeed dangerous -- if you
call you won't readily be able to unlock the Scroll_Lock -- let's instead
"make" (by concatenation) function (3-byte code "{Ascii-255}") and put it
at the Bottom of the Form (this implementation for v3.54+ only):

[ii]
SV01,SV02,XS01,02,03,04,05MSV02,SX04,IS03+IS02GT04EX



Differences Between GT and PV:
=============================

Most XPLers utilize command GT for execution of SUbroutines only (apropos of
nothing, be aware of the undocumented capacity of PV to also execute most
SUbs).  Generically, however, GT [probably should be "PV" -C.L.D.] is inadequately documented by XyQuest,
misunderstood, underrated, and underutilized.  Depending upon the situation,
GT either inserts string literals in text (faster than any other method!) or
else dumb-runs SUbroutines; while PV is a much more powerful code-handler that
is capable of *executing* code, including code *not contained in SUbroutines*.
If, for example, in routine [ii] above, we use AEPV04AF instead of AEGT04AF to put
the concatenated string AESX04AF into text, the effect is to *run* or *execute*
that concatenated string!  Routine [jj] is for v3.54+ only:

[jj]
SV01,SV02,XS01,02,03,04,05MSV02,SX04,IS03+IS02PV04 GT04 would put func BC in text; PV04 *executes* BC, and clears the CMline!EX

Routine [kk] does the same thing, but works in any XyWrite version:

[kk]
SU01,SX00,IS00FFGT01SV02,SX03,IS00+IS02  The CMline contains this text; now, hit a key and BC will clear it... SX04,RCMPV03PV03 prints this to the CMline, but GT03 puts func BC at Bottom FormGT03PR DoneEX

Routines [jjkk] demonstrate that, whereas GT requires a SUbroutine to execute
code, PV can take a string and execute it *as if* it were a SUbroutine (even
though it isn't) -- a remarkably powerful XPL tool.  [jjkk] also demonstrate
the difference between a "string literal" (a dumb string of bytes) and an
executing string:  AEPV03AF clears the CoMmand line, whereas AEGT03AF puts the
string literal "{Ascii-255}" (=) in text, where it is inert (but not
necessarily useless -- among many uses, you might put various functions and
strings in a text window, SAve the window, and then RUN it as a discreet PM).

Compare the results of code [ll]  (after running [ll], SAve and LIST it, to
view the byte-level results):

[ll]
SV01,AMPV01:    a 1-byte "A"
GT01:    a 1-byte "A"
LB AESV01AF is a 3 byte "41"SV01,41PV01:    a 1-byte "A"
GT01:    a 3-byte "A"
LB AESV01AF is a 5 byte "A" [Hex 41]SV01,FF41PV01:    a 3-byte "A"
GT01:  a 5-byte "A"
EX

Note that, in the above examples, "smart" PV transforms 3-byte strings into
1-byte strings, and 5-byte strings into 3-byte strings, whereas "dumb" GT
simply treats them literally (1-byte=1-byte, 3-byte=3-byte, 5=5).  Here's
another example, perhaps more useful:

[mm]
SV01,AEMGT01EX

The routine above, which contains a 3-byte Ascii-174 in AESV01AF, puts a passive
3-byte guillemet in text with AEGT01AF.  But if you change the code to AEPV01AF:

[nn]
SV01,AEMPV01EX

the guillemet is now alive (1-byte), and hard to handle.

GT bears to SV (and its relative SU) the same relationship that PV bears to
SX.  GT has no interpretive capabilities; but unlike PV, GT reads text in one
big gulp, and handles it "dumb" (whereas smart PV reads it character-by-
character and, if necessary, interprets it).  Thus, with a string of 1-byte
characters like AESV01, ABCDEFGHIJKLMNOPQRSTUVWXYZAF, watch what happens when
you put AESV01AF in text with these two code fragments ([oo] and [pp]):

[oo]
LB AEPV01AF inserts characters into text one-by-one (s-l-o-w-l-y)SV01, ABCDEFGHIJKLMNOPQRSTUVWXYZMPV01EX

whereas:

[pp]
LB AEGT01AF slams string AESV01AF into *text* instantaneouslySV01, ABCDEFGHIJKLMNOPQRSTUVWXYZMGT01EX

But two rules should be noted:  First, for command line insertion, PV must
be used -- GT *always* inserts in the text window.  Second, GT will always
*insert*, never *overstrike*, as the following code demonstrates (funcs
ought to force Overstrike on the CM line -- but the actual result is
entirely different):

[qq]
LB Will AEGT01AF force overstrike on the CoMmand line? SV01,ABCDEFGHIJKLMNOPQRSTUVWXYZMHello![[Hello![[GT01EX

It doesn't work.  GT insists upon the text window.  Note that everything else
in the routine works:  the cursor is *on* the CM line, and overstrike mode is
indeed active -- but notwithstanding these *preexisting* conditions, string
SV01 is *inserted in text* by GT.  Now compare PV:

[rr]
LB Will AEPV01AF force overstrike on the CoMmand line? SV01,ABCDEFGHIJKLMNOPQRSTUVWXYZMHello![[Hello![[PV01EX

With PV you end up on the CM line, and the last two characters of "Hello!" are
overstruck.  So, in appropriate situations, GT represents a very fast (but
rigid) way to put string literals in text, whereas PV is a powerful
interpretive tool (see "The PV Interpreter", below).

Let's now test what happens when we place strings that include the guillemet
control characters in text in Normal (formatted) edit mode.  GT first:

[ss]
SV01,LM0RM65MGT01EX

Now PV:

[tt]
SV01,LM0RM65MPV01EX

Both GT and PV accomplish the task, but GT is quiet and quick, while PV beeps
at you and commits errors (albeit, finally, benign errors) -- moreover, each
PV error incurs a time delay imposed by the second, "duration" value of the
Error Beep VAriable AEVAEBAF, which value you can see if you toggle into
Formatted editing mode right here >>VAEB<< .  I don't know how this value
is quantified -- possibly in 1/100,000s of a second @ 4.77MHz -- but the
hesitation produced by the VAEB delay (unless set to zero) noticeably retards
PM execution.  So PV is clearly undesirable in the above situation.  Observe,
however, that in *Expanded* text mode, PV works fine:

[uu]
SV01,LM0RM65MPV01EX

The more sophisticated your programs become, the less likely you are to have
success at all times with GT, because GT is "dumb".  For instance, suppose a
program obtains a formatting value from within the PM itself, either from user
input or by other means.  In the following code, the length of a user-name
string is used to determine a right margin value (assumption:  AEPT1AF is a
12cpi non-proportional font):

[vv]
LB User inputs his name -- Anemone Onomono -- which is captured in AESV01AF, and then...SV01,AnemoneOnomonoSX02,@SIZ(IS01)+1M0DSV03,PT1LM0GT03rm PV02	0DLBAGT01IFPV02>0SX02,PV02-1GLAEIEX

Note that since AEPT1AF and AELM0AF are hardcoded, they're placed in text with
AEGT03AF.  But we can't hardcode the right-margin value, so in [vv] we go
to the CM line and put "AERM15AF" in text with rm PV02	.  If you're
tempted to try this:

[ww]
SV01,AnemoneOnomonoSX02,@SIZ(IS01)+1M0DSV03,PT1LM0RMPV02GT03EX

it won't work because AESV03AF is a string literal; GT has no interpretive
capability, i.e. it cannot interpret PV02 to obtain its underlying value
(15) but rather reads AEPV02AF simply as a literal, which gets placed in text:
...AEPT1AFAELM0AFAERMAEPV02AFAF...  "AEPV02AF" is a nonsensical Right Margin argument,
so XyWrite beeps *very* persistently, until you fix it, or until you toggle
into Expanded text mode.

But, let's modify our attack and use PV (supposed to be "smarter") instead of
GT, and try it in Expanded mode:

[xx]
SV01,AnemoneOnomonoSX02,@SIZ(IS01)+1M0DSV03,PT1LM0SV04,RMSV05,GT03PV04PV02PV05EX

Still no cigar.  The essential problem is that AESV04AF contains an Extra start
command -- AERM -- an unmatched Ascii-174.  So, XyWrite parses the content of
SV04 as this string literal:  "AERMAFAESV05,AF"; what we intended to be the
terminating guillemet of AESV05AF is instead interpreted to be the terminating
guillemet of AESV04AF (and AESV05AF no longer exists)!  Clearly, this whole
approach is untenable.  Manipulation of lone guillemets is the real answer.

[yy]
SU01,SX05,IS00AEGT01SX04,IS05AFGT01SV01,AnemoneOnomonoSX02,@SIZ(IS01)+1M0DSV03,PT1LM0SV06,RMSX03,IS03+IS04+IS06+IS02+IS05GT030DLBAGT01IFPV02>0SX02,PV02-1GLAEIEX

What's the underlying structure of concatenation AESX03AF, above?
code:         AESX03,  AEIS03AF   +AEIS04AF+AEIS06AF+AEIS02AF+AEIS05AFAF
which means:  AESX03=AEPT1AFAELM0AF +  AE   +  RM  +  15  +  AF   AF

There are several other ways to handle this.  If:
  1) you simply cannot go to the CoMmand line during your routine, AND
  2) your intention is to place guillemets in a real-time text window, AND
  3) you can operate in eXPanded text mode
any version of XyWrite III(+) will accept the following (loading 3-byte 174
and 175 on AESV04AF and AESV05AF respectively):

[zz]
SV04,AESV05,AFSV01,AnemoneOnomonoSX02,@SIZ(IS01)+1M0DPT1LM0PV04RMPV02PV05EX

Unfortunately, toggles between Normal and Expanded text modes are very time
consuming.  But note well, that most XPL PMs which insert or otherwise
manipulate text will run *much* faster in Expanded mode, because there's no
time lost reformatting the screen.  The situation is similar in normal
editing:  screen paging works much faster in Expanded mode than in Normal
mode.

In your own personal programming, you can put Ascii 174 and 175 onto separate
global (permanent) Save/Gets in STARTUP.INT, and never run the routine again
(but you may not issue CLRXSGT or CLRASG at any subsequent time, nor may any
program usurp these dedicated Save/Gets):

In STARTUP.INT, get Ascii-174 on AESV998AF and Ascii-175 on AESV999AF, using
3-byte source strings "AE" and "AF" (inspect this PM in Normal editing mode):

[aaa]
SX01,SX999,IS00AEGT01SX998,IS999AFGT01default ....

But [aaa] is too complex for generic programming; few off-the-shelf users
are patient with extensive changes to STARTUP.INT etc. (nor do they know *how*
to generate functions, guillemets, and so forth).  *Very few* users have any
acquaintance with XPL!  "Public" PMs should involve as little configuration
as possible.

If a concern to preserve the contents of the CoMmand line throughout an XPL
routine inhibits you from using the CMline to get 174, 175, 255, etc, the
following offers a solution.  Put the contents of the CMline onto a Save/Get
when you initialize, and then *restore* it when you terminate:

[bbb]
 SV02 holds this initial CoMmand lineSU01,SX04,IS00GT01SX02,IS04AEGT01SX03,IS04AFGT01PV02; and SV03SV04 now hold 1745: PV03PV04EX



Concatenation:
=============

Routine [yy] above hints at the power of concatenation.  In fact, using
concatenation, you can actually *create* whole programs from scratch within a
parent PM, and then RUN those programs as child processes.  It takes work and
clear thinking, but it is very often the only solution to complex XPL
problems.  A simple example is a manufactured PRompt.  PRompts are string
literals, and so are almost always hard-coded.  AEPR All done!AF is such a
hard-coded PRompt.  Try to run this:

[ccc]
 Enter a letter or number:  SX01,RCPR You chose "PV01"  DoneEX

[ccc] doesn't work because PRompts are string literals, and "AEPV01AF" appears
in the PRompt *literally*.  Concatenation is the solution (in addition to
generating the correct PRompt in [ddd], we also insert the concatenated string
"literal" at Bottom Form in order to display its full content):

[ddd]
SU02,SX00,IS00AEGT02SX01,IS00AFGT02 Enter a letter or number:  SX03,RCSV04,PR You chose "SV05,"  DoneSV06,EXSX07,IS01+IS04+IS03+IS05+IS00+IS06M0D0DGT07PV07EX

Several things are noteworthy in [ddd].  First, you *must* put a func at
the conclusion of the concatenation, in order to avoid a (mis-named) "Extra
start command" error, i.e. two Ascii 175s in a row at the end of the string.
In other words, if the end of concatenation AESX07AF instead read
"...AEIS00AFAFAEPV07AF...", then AEIS00AF would be Ascii 175, and the end of the
concatenation is also an Ascii 175, and XyWrite is incapable of parsing the
concatenation.  (That's the way it is, sorry!)  Function inserted between
these 175s overcomes the error.  But, second, func itself *cancels* the
PRompt you're trying to display, because PRompts are erased on the first
occurrence of any function.  Therefore, you must EXit *before* func !

Here's the underlying structure of concatenation AESX07AF in [ddd]:
code:         AESX07,AEIS01AF+    AEIS04AF      +AEIS03AF+  AEIS05AF  +AEIS00AF+AEIS06AF AF
which means:  AESX07=  AE   + PR You chose " + char + "  Done +  AF   +AEEXAFAF

When we AEPV07AF, the manufactured PRompt is displayed.  Son of a bitch.  This
opens a genuine world of possibilities.



The PV Interpreter:
==================

Now, take it one step further.  Suppose you need to make a *new* Save/Get (one
not used in your program) to contain discreet fields of data, the number and
content of which will be unknown until runtime.  It could be any data -- for
example, capture the contents of the command line and store it for future use;
or it could be a program which was constructed from user-supplied data, and
will be run as a child process.  To prove that we've really made a Save/Get
where none previously existed, we'll display all the "manufactured" Save/Gets
in program [eee] at Bottom Form.  Note that none of this would be remotely
possible without loading Ascii 174 and 175 on separate Save/Gets:

[eee]
LB 
  Open a window, check for ERror, set eXPanded text mode 
ca con	IFERPR No window availableEXEILB 
  Get Ascii 174175 on Save/Gets AESV01AF and AESV02AF with AESU03AF 
SU03,SX02,IS00AEGT03SX01,IS02AFGT03LB 
  Set strings and variables, re-use AESV03AF because we're done with AESU03AF, 
  set AESX05AF to first unused Save/Get number (=12) 
SV03,	
SV04,SXSX05,12SV06,,IS07SV08,LB 
  SUbroutine to obtain data for fields 
SU09,SV07, Terminate data-entry with <cr> on EMPTY field.  Field PV10:  LBAPR <cr> to end entrySX11,RCIFIS11IS03<0PV11SX07,IS07+IS11GLAEISX11,IS01+IS04+IS05+IS06+IS02+IS08LB 
  Repeatedly run AESU09AF, put AESX11AF, and increment AESX05AF and AESX10AF by 1, 
  until we encounter <cr>	on an empty field 
SX10,1LBBGT09IF@SIZ(IS07)>0PV11SX05,PV05+1SX10,PV10+1GLBEILB 
  Set string AESV04AF, and re-use Save/Get 09 as new SUbroutine, to display all 
  "manufactured" Save/Gets 
SV04,PVSU09,SX10,IS03SX11,IS01+IS04+IS10+IS02+IS08LB 
  Display all "manufactured" Save/Gets in routine at Bottom Form 
MSX03,12LBCGT09SX06,PV03-11AESVPV10AF (Data Field #PV06):  PV110DIFPV03<PV05-1SX03,PV03+1GLCEIPR DoneEX

The first concatenation AESX11AF is the key to code [eee].
Suppose Data Field #1 contains the proper name "Jeff":

code:    AESX11,AEIS01AF+AEIS04AF+AEIS05AF+  AEIS06AF +AEIS02AF+AEIS08AFAF
means:   AESX11,  AE   +  SX  +  12  + ,AEIS07AF +  AF   +   AF
or:      AESX11,AESX12,AEIS07AFAFAF

Does AESX11AF contain the name "Jeff"?  No!  Above, it contains only a *string
literal*, namely "AESX12,AEIS07AFAF".  Well then, does *AESX12AF* contain the
name "Jeff"?  No.  In fact, AESX12AF does not yet exist!  But, using the
powerful PV command, we can transform this string literal into live code.  All
we have to do is AEPV11AF!

"PV" means "Put Value", and indeed, I think PV was conceived (long ago)
exclusively as a number-handler.  But it is more.

This is *important*:  PV has two distinct rles.  First, as a *numeric
argument* for SX, e.g. ...AESX01,9AFAESX02,AEPV01AF-3AF...  In that fragment, AESX02AF
holds a result of 6.  If AEPV01AF were not a *number* (9), the fragment would
crash!  But Second, as we've seen in numerous examples above, *by itself* PV
can also be a *command*.  You can PV text into a window or the CM line, e.g.
AESV01,HelloAFAEPV01AF.  You can eXeCute SUbroutines with PV.  And you can
eXeCute very wierd concatenations like the ones in [eee], where PV "runs"
AESX11AF so that AESX11AF puts the content of AESV07AF ("Jeff") into AESX12AF.  With
this, AESV12AF comes into being, and contains "Jeff".  QED.



TABLES
======

Complete Table of the Ascii 0-255 Character Set, expressed in 3-byte codes:

  000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748
  494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F9091
  92939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DA
  DBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF

The "character set" above looks just like the standard Ascii character set.
But LIST it to see how it appears in true WYSIWYG.  A different beast
altogether!  A simple way to put 3-byte characters into any text file is to
CoPy them from the table above.  Some programming and keyboard methods for
generating specific 3-byte chars were exampled previously.

The following routine generates any 3-byte character, based upon its decimal
value, for "on-the-fly" insertion in text.  It works in any XyWrite version
(faster, more succinct routines are available in v3.54+).  More interesting,
[fff] shows how to use the CoMmand line as "workspace" for parsing short
strings (no longer than the length of the CMline, i.e. about 77 characters)
(we avoid SUbroutines in this part of routine [fff], so that the code is
clearer).  The command line can rescue many a program which would otherwise be
possible only in v3.54+ using the XS parser:

[fff]
LB Make any 3-byte CHARACTER Ascii 0-255, and insert char in text at current cursor position  DECIMAL VERSION  works in any XyWrite IIINota Bene version SV01,	
SV02,SV03,SV05,0123456789 Insert 3-byte code in text.  Input decimal [Ascii] value of char:  LBAPR <cr>XC to end; `Esc' abortsSX04,RCIFIS04==IS02LBB}PR AbortEXEIIFIS04IS01>-1GLCEIIFIS04IS05>-1PV04SX03,IS03+IS04EIIF@SIZ(IS03)<3GLAEILBCIF@SIZ(IS03)<1 No valueGLBEIIFPV03>255 Bad value: PV03GLBEISU01,SX02,0LBDIFPV03>15SX03,PV03-16SX02,PV02+1GLDEIGT01SU05,SX00,IS00LBESV01,0123456789ABCDEFSX04,0PV01wLBFIFPV04<PV02ϮSX04,PV04+1GLFEIcӮGT05SX06,IS00SX04,0PV01wLBGIFPV04<PV03ϮSX04,PV04+1GLGEIcӮGT05SX06,IS06+IS00FFGT05 SV02,FFSX06,IS00+IS02+IS06}PV06PR DoneEX

[ggg] does the same thing, but with hex input (e.g. input "AE", get a 3-byte
"AE" in text):

[ggg]
LB Make any 3-byte CHARACTER Ascii 0-255, and insert char in text at current cursor position  HEX VERSION  works in any XyWrite IIINota Bene version SV02,SV03,SV05,0123456789ABCDEF Insert 3-byte code in text.  Input hex value of char:  LBAPR <cr>XC to end; `Esc' abortsSX04,@UPR(RC)IFIS04==IS02LBB}PR AbortEXEIIFIS04IS05>-1PV04SX03,IS03+IS04EIIF@SIZ(IS03)<2GLAEILBCIF@SIZ(IS03)<1 No valueGLBEISU04,SX00,IS00FFGT04 SV02,FFSX03,IS00+IS02+IS03}PV03PR DoneEX

You can alter routines [fff] and [ggg] to insert *1-byte* codes simply by
changing AESV02,FFAF in the last line of each routine to AESV02,AF.  But watch out
with the control characters!



          Actual-Source-Char(s)=Displayed-Result-Char(s) Result-Byte-Length
         ͻ
CHAR DEC       .KBD File       External  FileFuncTxt PV  GTTxt PV  GT
Srce_Len1A (1)  (3)     (5)   (1)    (3)   Rn   (1)   XPL   (3)   
---- --- Ķ
       0  = 0  = 0FF00=  3  = 000=  3=  3NA  0  00  0   3
 08     8 08=081!08 =081!FF08=08 308 =081!08=08 3=08 3081! 081! 081081! 081! 083
 09     9 09=09 109 =09 1FF09=09 309 =09 109=09 3=09 3091  091  091091  091  093
 0A    10  NA  0A = 0FF0A=0A 30A =0A 10A=0A 3=0A 30  0  0A10  0  0A3
 0D    13  NA  0D =1B 2FF0D=0D 30D =1B 10D=0D 3=0D 31B2  1B2  1B11B2  1B2  0D3
0D0A 13+10  NA  0D0A=1B 2see 0D+0A 60D0A=1B 2see0D+0A6=0D0A61B2  1B2  1B21B2  1B2 0D0A6
     16 = 1 = 1FF10= 3 = 110= 3= 11  1  11  1  3
 11    17 11=11 111 =11 1FF11=11 311 =11 111=11 3=11 3111  111  111111  111  113
 1A    26  NA  1A = 0FF1A=1A 31A = 11A=1A 3=1A 3NA  NA  NA0  0  1A3
 1B    27 1B= 11B = 1FF1B=1B 31B = 11B=1B 3=1B 31  1  11  1  1B3
      32  =  1  =  1FF20=  3  =  120=  3=  3 1   1   1 1   1   3
 7E   126 7E=7E 17E =7E 1FF7E=7E 37E =7E 17E=7E 3=7E 37E1  7E1  7E17E1  7E1  7E3
 AE   174 AE=AE 1AE =AE 1FFAE=AE 3AE =AE 1AE=AE 3=AE 3AE1  NA  NAAE1  AE1  AE3
 AF   175 AF=AF 1AF =AF 1FFAF=AF 3AF =AF 1AF=AF 3=AF 3AF1  NA  NAAF1  AF1  AF3
 FD   253  NA  FD =FD 1FFFD=FD 3FD =FD 3FD=FD 3=FD 3NA  NA  NAFD1  FD1  FD3
     255  NA   =1FFFF=  3 =1FF= 3= 3NA  NA  NA1 1 3
         ͼ
   Null Result
  ! Performs DOS function, e.g. "08" Back Deletes
   XyWrite does not read files beyond Ascii-26, the End-of-File char
   Ascii-255
   Ascii-255 binds with the next 2 chars, with varied visual results
   "5-byte" codes in .KBD are coded in one of two ways, either e.g.
      Tab:  15=NO,{3-byte 255},0,9   *or*   15=R9
      Guillemet "AE":  51=NO,{3-byte 255},A,E   *or*   51=R1,R7,R4
   Function Rn on the CoMmand line yields a 1-byte result (3-byte codes
      placed on the CoMmand line always yield 1-byte results)
  NA Not AvailableImpossibleMay Crash the File, PM, or even XyWrite
  The "Txt", "PV", and "GT" columns in the XPL box, above-right, distinguish
      3 methods for putting strings (e.g. "Hello") into text with XPL:
        Txt:  ...}Hello...
        PV:   ...}AESV01,HelloAFAEPV01AF...
        GT:   ...}AESV01,HelloAFAEGT01AF...



Version of MDRVControl Character TableMDNM suitable for HELP file:
---------------------------------------------------------
CoPy the table between the carets "^" (*excluding* the carets) into .HLP, and
then insert the following line in your .HeLP INDEX at marker "{{6b}}:

byte sequences	MDBObytesMDNM

Then SAve the HELP file, and LOAD it.

^{{6bytes}}
           MDULActual-Source-Char(s)=Displayed-Result-Char(s) Result-Byte-LengthMDNM
MDRVCharMDNM MDRVDecMDNM       MDRV.KBD FileMDNM       MDRVExternal  FileMDNMMDRVFuncMDNMTxt PV  GTTxt PV  GT
MDFUSrce-LenMDNM1AMDUL (MDFU1MDUL)  (MDFU3MDUL)     (MDFU5MDUL)    (MDFU1MDUL)    (MDFU3MDUL)  MDBUR0-9MDUL   (MDFU1MDUL)   MDRVXPLMDUL   (MDFU3MDUL)   MDNM
       0  = 0  = 0FF00=  3  = 000=  3=  3NA  0  00  0   3
 08     8 08=081!08 =081!FF08=08 308 =081!08=08 3=08 3081! 081! 081081! 081! 083
 09     9 09=09 109 =09 1FF09=09 309 =09 109=09 3=09 3091  091  091091  091  093
 0A    10  NA  0A = 0FF0A=0A 30A =0A 10A=0A 3=0A 30  0  0A10  0  0A3
 0D    13  NA  0D =1B 2FF0D=0D 30D =1B 10D=0D 3=0D 31B2  1B2  1B11B2  1B2  0D3
0D0A 13+10  NA  0D0A=1B 2see 0D+0A 60D0A=1B 2see0D+0A6=0D0A61B2  1B2  1B21B2  1B2 0D0A6
     16 = 1 = 1FF10= 3 = 110= 3= 11  1  11  1  3
 11    17 11=11 111 =11 1FF11=11 311 =11 111=11 3=11 3111  111  111111  111  113
 1A    26  NA  1A = 0FF1A=1A 31A = 1!1A=1A 3=1A 3NA  NA  NA0  0  1A3
 1B    27 1B= 11B = 1FF1B=1B 31B = 11B=1B 3=1B 31  1  11  1  1B3
      32  =  1  =  1FF20=  3  =  120=  3=  3 1   1   1 1   1   3
 7E   126 7E=7E 17E =7E 1FF7E=7E 37E =7E 17E=7E 3=7E 37E1  7E1  7E17E1  7E1  7E3
 AE   174 AE=AE 1AE =AE 1FFAE=AE 3AE =AE 1AE=AE 3=AE 3AE1  NA  NAAE1  AE1  AE3
 AF   175 AF=AF 1AF =AF 1FFAF=AF 3AF =AF 1AF=AF 3=AF 3AF1  NA  NAAF1  AF1  AF3
 FD   253  NA  FD =FD 1FFFD=FD 3FD =FD 3FD=FD 3=FD 3NA  NA  NAFD1  FD1  FD3
     255  NA   =1FFFF=  3 =1FF= 3= 3NA  NA  NA1 1 3
!=Performs DOS function; =Null Result; =Ascii-255; =Binds to next 2 chars

^


Versions of Tables, suitable for HELP file:
------------------------------------------
   MDRVAscii Character TableMDNM
   MDRVHex Character TableMDNM
   MDRVAscii-Hex Value Translation TableMDNM

CoPy the table between the carets "^" (*excluding* the carets) into .HLP, and
then insert the following line in your .HeLP INDEX at marker "{{6c}}:

character sets (dechex)	MDBOcharsetsMDNM

Make sure that "{{8MORE}}" and "{{8MORE1}}" do not appear elsewhere in .HeLP
as markers.

^{{6charsets}}
 0=00 20= 40=( 60=< 80=P 100=d 120=x 140= 160= 180= 200= 220= 240=
 1= 21= 41=) 61== 81=Q 101=e 121=y 141= 161= 181= 201= 221= 241=
 2= 22= 42=* 62=> 82=R 102=f 122=z 142= 162= 182= 202= 222= 242=
 3= 23= 43=+ 63=? 83=S 103=g 123={ 143= 163= 183= 203= 223= 243=
 4= 24= 44=, 64=@ 84=T 104=h 124=| 144= 164= 184= 204= 224= 244=
 5= 25= 45=2D 65=A 85=U 105=i 125=} 145= 165= 185= 205= 225= 245=
 6= 26=1A 46=. 66=B 86=V 106=j 126=7E 146= 166= 186= 206= 226= 246=
 7= 27=1B 47=/ 67=C 87=W 107=k 127= 147= 167= 187= 207= 227= 247=
 8=08 28= 48=0 68=D 88=X 108=l 128= 148= 168= 188= 208= 228= 248=
 9=09 29= 49=1 69=E 89=Y 109=m 129= 149= 169= 189= 209= 229= 249=
10=0A 30= 50=2 70=F 90=Z 110=n 130= 150= 170= 190= 210= 230= 250=
11= 31= 51=3 71=G 91=[ 111=o 131= 151= 171= 191= 211= 231= 251=
12= 32=20 52=4 72=H 92=\ 112=p 132= 152= 172= 192= 212= 232= 252=
13=0D 33=! 53=5 73=I 93=] 113=q 133= 153= 173= 193= 213= 233= 253=FD
14= 34=" 54=6 74=J 94=^ 114=r 134= 154= 174=AE 194= 214= 234= 254=FE
15= 35=# 55=7 75=K 95=_ 115=s 135= 155= 175=AF 195= 215= 235= 255=FF
16= 36=$ 56=8 76=L 96=` 116=t 136= 156= 176= 196= 216= 236=  MDRVAsciiMDNM
17=11 37=% 57=9 77=M 97=a 117=u 137= 157= 177= 197= 217= 237=   MDRVSetMDNM
18= 38=& 58=: 78=N 98=b 118=v 138= 158= 178= 198= 218= 238=
19= 39=' 59=; 79=O 99=c 119=w 139= 159= 179= 199= 219= 239=  MDBOMOREMDNM

{{8MORE}}
00=00 14= 28=( 3C=< 50=P  64=d  78=x  8C=  A0=  B4=  C8=  DC=  F0=
01= 15= 29=) 3D== 51=Q  65=e  79=y  8D=  A1=  B5=  C9=  DD=  F1=
02= 16= 2A=* 3E=> 52=R  66=f  7A=z  8E=  A2=  B6=  CA=  DE=  F2=
03= 17= 2B=+ 3F=? 53=S  67=g  7B={  8F=  A3=  B7=  CB=  DF=  F3=
04= 18= 2C=, 40=@ 54=T  68=h  7C=|  90=  A4=  B8=  CC=  E0=  F4=
05= 19= 2D=2D 41=A 55=U  69=i  7D=}  91=  A5=  B9=  CD=  E1=  F5=
06= 1A=1A 2E=. 42=B 56=V  6A=j  7E=7E  92=  A6=  BA=  CE=  E2=  F6=
07= 1B=1B 2F=/ 43=C 57=W  6B=k  7F=  93=  A7=  BB=  CF=  E3=  F7=
08=08 1C= 30=0 44=D 58=X  6C=l  80=  94=  A8=  BC=  D0=  E4=  F8=
09=09 1D= 31=1 45=E 59=Y  6D=m  81=  95=  A9=  BD=  D1=  E5=  F9=
0A=0A 1E= 32=2 46=F 5A=Z  6E=n  82=  96=  AA=  BE=  D2=  E6=  FA=
0B= 1F= 33=3 47=G 5B=[  6F=o  83=  97=  AB=  BF=  D3=  E7=  FB=
0C= 20=20 34=4 48=H 5C=\  70=p  84=  98=  AC=  C0=  D4=  E8=  FC=
0D=0D 21=! 35=5 49=I 5D=]  71=q  85=  99=  AD=  C1=  D5=  E9=  FD=FD
0E= 22=" 36=6 4A=J 5E=^  72=r  86=  9A=  AE=AE  C2=  D6=  EA=  FE=FE
0F= 23=# 37=7 4B=K 5F=_  73=s  87=  9B=  AF=AF  C3=  D7=  EB=  FF=FF
10= 24=$ 38=8 4C=L 60=`  74=t  88=  9C=  B0=  C4=  D8=  EC=
11=11 25=% 39=9 4D=M 61=a  75=u  89=  9D=  B1=  C5=  D9=  ED=  MDRVHex SetMDNM
12= 26=& 3A=: 4E=N 62=b  76=v  8A=  9E=  B2=  C6=  DA=  EE=
13= 27=' 3B=; 4F=O 63=c  77=w  8B=  9F=  B3=  C7=  DB=  EF=  MDBOMORE1MDNM

{{8MORE1}}
0=0020=1440=2860=3c80=5000=6420=7840=8c60=a080=b400=c820=dc40=f0
1=0121=1541=2961=3d81=5101=6521=7941=8d61=a181=b501=c921=dd41=f1
2=0222=1642=2a62=3e82=5202=6622=7a42=8e62=a282=b602=ca22=de42=f2
3=0323=1743=2b63=3f83=5303=6723=7b43=8f63=a383=b703=cb23=df43=f3
4=0424=1844=2c64=4084=5404=6824=7c44=9064=a484=b804=cc24=e044=f4
5=0525=1945=2d65=4185=5505=6925=7d45=9165=a585=b905=cd25=e145=f5
6=0626=1a46=2e66=4286=5606=6a26=7e46=9266=a686=ba06=ce26=e246=f6
7=0727=1b47=2f67=4387=5707=6b27=7f47=9367=a787=bb07=cf27=e347=f7
8=0828=1c48=3068=4488=5808=6c28=8048=9468=a888=bc08=d028=e448=f8
9=0929=1d49=3169=4589=5909=6d29=8149=9569=a989=bd09=d129=e549=f9
0=0a30=1e50=3270=4690=5a10=6e30=8250=9670=aa90=be10=d230=e650=fa
110a31=1f51=3371=4791=5b11=6f31=8351=9771=ab91=bf11=d331=e751=fb
120c32=2052=3472=4892=5c12=7032=8452=9872=ac92=c012=d432=e852=fc
130d33=2153=3573=4993=5d13=7133=8553=9973=ad93=c113=d533=e953=fd
140e34=2254=3674=4a94=5e14=7234=8654=9a74=ae94=c214=d634=ea54=fe
150f35=2355=3775=4b95=5f15=7335=8755=9b75=af95=c315=d735=eb55=ff
161036=2456=3876=4c96=6016=7436=8856=9c76=b096=c416=d836=ecMDRVAsciiMDNM
171137=2557=3977=4d97=6117=7537=8957=9d77=b197=c517=d937=edMDRV>>HexMDNM
181238=2658=3a78=4e98=6218=7638=8a58=9e78=b298=c618=da38=eeMDRVCon- MDNM
191339=2759=3b79=4f99=6319=7739=8b59=9f79=b399=c719=db39=efMDRV vertMDNM

^


Function Table (accurate through v3.55)

^{{6funcSE}}
TS20,80 MDFUMDBOMORE_FUNCSMDNM	ccFF''сѳ''KKWW
	ee))Ӂӳ))YY
	gg++Ձճ++[[
	ii--ׁ׳--++]]
	kk//فٳ//MM__
Precede two	mm	09B3ہ۳	0911OO
SEarch chars	oo݁ݳ33QQaa
tabled here	qq
0D߁߳
0D55cc
with Ascii_255	ss77ee
	111199gg
	uu;;
	ww==ii
	yy??
	{{ÁóAAkk
	}}ŁųCC77
	ǁǳEEoo
	ɁɳGG??
	!!ˁ˳!!qqSSqq
	##́ͳ##IIUU
	MDSU$AMDNM FD%%ρϳ%%ss

{{6MORE_FUNCS}}
TS20,80 MDFUMD15MORE_FUNCSMDNM	
0D}}рѳ
	uu33CC}}Ӏӳ))
	AA]]ՀճUU
	__yyEE==
	YY׀׳uu
Precede two	[[ـٳSS
SEarch chars	ۀ۳
tabled here	wwaa݀ݳ99
with Ascii_255	KK55
	yy!!ooGG11MM
	{{11wwmmMDSUWCMDNM FD
	kk##--AF
	OO33//FF
	;;''ÀóWW
	gg55ŀų
	QQ{{AFǀǳ
	iiMMɀɳ߀߳
	ss77%%B3ˀ˳SSII
	̀ͳ	09
	mmπϳ

^


Addendum for XyWrite 4+ (from STACK.DOC 4/15/95 [LastRev.1/18/04]):

Coffee Break:  One-Byte, Three-Byte, and Five-Byte Characters
============   --------  ----------  --- --------- ----------
About a dozen characters in the 256-char set are reserved to XyWrite's use.
The most important of these is Ascii-255, which is used in XyWrite as the
first byte in special 3-byte strings called, either, "functions" (e.g. )
or "3-byte characters".  Functions and 3-byte chars have separate purposes
and different appearances on-screen, but they share two features:  both are
3-bytes long, and both begin with Ascii-255.

When we type one of Xy4's dozen or so reserved characters, XyWrite prints
to the screen a 3-byte character in its place.  On-screen, 3-byte
characters look the same as 1-byte characters; within XyWrite, you cannot
see any visual difference.  But at the byte level (and outside XyWrite),
3-byte chars have only a mathematical relationship to the 1-byte chars they
replace -- visually there is *no* relationship.  The first byte of a 3-byte
char is Ascii-255; the second and third bytes are the hexadecimal value of
the Ascii number being replaced.  Thus, the 3-byte string for an
OpenGuillemet (Ascii-174=Hex-AE) is "{Ascii-255}AE".  Here's one: "AE".  It
*looks like*, but in fact is *not*, a real 1-byte guillemet Ascii-174 of
the kind used in XPL expressions.  Similarly, a 3-byte Ascii-255 is
composed of "{Ascii-255}FF", because "FF" is the hexadecimal value of 255.

Functions also begin with Ascii-255.  The second byte in a 3-byte function
string is Ascii-128, 129, or 130.  The third byte is an arbitrarily-
selected character.  When we print a function to the screen, Xy4 internally
translates it into the function *name* that it represents, and prints that
name to the screen, e.g. "}" or "".  But what are GT and BX really?
"{Ascii-255}}" and "{Ascii-255}".  From a user standpoint, the
underlying coding of functions seldom matters; what's important is that all
functions begin with Ascii-255, and that Ascii-255 is itself one of Xy4's
reserved characters.  To print 255 to the screen in a XyWrite window, as
here, we *must* use it's 3-byte form:
"FF" <==in CodePages 437 and 850, it appears to be a blank space;
       in CodePage 1252 (Windows ANSI), a y-umlaut

Let's examine what happens when a special 3-byte string is moved between
the text and the command line, or from a Save/Get to the command line.  If
you have XY4.KBD or XY4-3.KBD loaded, DeFine the three characters here:
"FF}"
and then hit Alt-Shift-Ctrl-C (this CoPies DeFined text to the
CMline).  "}" gets printed on the CMline!  Why?  Think about what we've
written here:  "FF}".  That first (blank) byte is Ascii-255.  We couldn't
write it here if that 255 wasn't in special 3-byte form *already*.  So if
we add "}" to this 3-byte 255, we have a *5-byte string*!  Get it?
5-byte$ for }="FF}"; 3-byte$ for }="}".

Two *rules*:
  1) If you type Ascii-255 in text, it is in 3-byte form
  2) If you move a 3-byte character from text to the CMline, it becomes a
     1-byte character (with some Sig|Xy4 exceptions; in Xy3+ this
     rule was inflexible, but Sig|Xy4 transform e.g. a 3-byte
     OpenGuillemet "AE" into ]or .)

So, when you moved the 5-byte "FF}" to the CMline, it became a 1-byte 255
plus "}", or a genuine 3-byte }.  Now, try this:  DeFine function >}<
between the "><" characters.  Hit Alt-Shift-Ctrl-C.  What happens?  The
cursor goes to the CMline and function GT (GoText) *executes*, which
immediately moves the cursor off the CMline and back into the Text window
again.

The rules here are, that if you put a genuine 3-byte string on the CMline,
it does what it is designed to do:  it executes if a function (}does its
job), or it displays as a 1-byte character (3-byte "41" becomes a 1-byte
"A").  Whereas if you put a 5-byte string on the CMline, it is reduced to a
passive 3-byte representation of itself ("FF}" becomes "}", "FF41" becomes
"41").  A final rule, important for Stack, is that there is no essential
difference between XyWrite's string handling when it moves from the Text
Window to the CMline, or when it moves from a stored Save/Get to the
CMline.  QED.

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

