---------------------------------------------------------------
QL Brouhabouha Forth 1994-05-15
---------------------------------------------------------------

Distribution is welcome, but ONLY allowed with all original
textfiles being at least part of what is distributed, and the
executable file remains the original one.

All rights reserved @ Ewald Pfau, 1991-1994.

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

This is a supplement to file: Brouha.Txt

Contents:
-- Words and tools not covered by ANS paper
-- The block file editor

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

*****************************************************
         ** Words not covered by dpANS **
*****************************************************

- Words available in general Forth-Wordlist -------------------

U<=>       ( u1 u2 -- -1/0/1)
Compare unsigned two values given, return 0 if both are the
same, -1 if the value next on stack is smaller than the value on
top of stack, 1 otherwise.

CASE?      ( n1 n2 -- n1 0 // -1)
Compare two values given, return -1 if both are the same,
elsewise leave the value next on stack and zero on top of stack.

UMIN       ( u1 u2 -- u3)
Leave unsigned the smaller one from two values given.

UMAX       ( u1 u2 -- u3)
Leave unsigned the bigger one from two values given.

$CRC16+    ( n0 a n -- n1)
Apply a cyclic redundancy check calculation to the string in
memory given by its parameters, address and length, starting
with the accumulating value given as the next but one value on
stack, returning the accumulated value.

CREATE-JOB ( #code #data -- a job-id err#)
PJOB       ( priority job-id -- err#)
AJOB       ( priority 0/-1 job-id -- err#)
SUSJOB     ( #ticks job-id -- err#)
RELJOB     ( job-id -- err#)

F#@        ( id -- channel#)
Lookup the OS specific channel number of the handle number
as it has been returned by OPEN-FILE or by CREATE-FILE.

IN-CHANNEL
Variable, containing the handle number used for input from
keyboard.

CRT-CHANNEL
Variable, containing the handle number used for output to
console.

CSIZE
PAPER
INK
CURS-ON

DEL        ( --)
Destructive backspace is output on console window if cursor is
not already in first column.

SKIP       ( a n char -- a+ n-)
SCAN       ( a n char -- a+ n-)

CAPS       ( -- a)
Address of a variable in which -1 is kept if some system words
shall act case independant. These are FIND and SEARCH-WORDLIST
for the interpreter as well as COMPARE and SEARCH for string
words. Writing 0 to CAPS will switch to case dependant
behaviour.

CAPITAL    ( char -- char)
A given character is returned uppercased.

STACK|     ( ix..iy -- ix..iy // "abcd...|xyz..|")
Rearrange the order of values on stack, taking each letter of a
first series of letters up to a first pipe sign '|', to be one
item on stack in the order as is, the last letter representing
the value on top of stack, and rearrange, or as well duplicate
or drop, following the series of letters up to a trailing pipe
sign.

USE        ( -- // "name")
To the block file system, file <name> is assigned to. This file
is opened and the file handle is stored in variable BLOCK-FID.
If a block file already has been open with it's file handle
stored in BLOCK-FID, it is closed after the new file could be
opened.

If on the same drive the medium is to be changed, and a file is
open on the first medium, so this file should be closed by:
" BLOCK-FID @ CLOSE-FILE THROW  0 BLOCK-FID ! ".

LOAD-FILE  ( n hdl --)
A file represented by a file handle is regarded to be a block
file, the value stored in BLOCK-FID is saved, the block number
given is loaded as with LOAD, and BLOCK-FID restored afterwards.

SAVE-FILE  ( a n -- err#)
An image of the momentary running executable is saved as a file
the name of which given by its parameters, address and length. A
nonzero value is returned if operation failed.

GET-SIZES       ( -- #code #data #hdrs)
Three values are returned on stack reflecting the amount of
memory sizes the executable would claim from the operating
system at next startup. These are for maximum size of code, of
data, and, as top of stack, of headers.

ADJUST-SIZES    ( #code #data #hdrs --)
Three values are taken from stack to be the sizes of memory
which will be claimed from operating system more than
momentarily needed, at next start-up of the momentary running
executable, if it is saved after adjusting sizes by SAVE-FILE.
The values are for additional size of code, of data and of
headers area, the last one being expected as top of stack. All
parameters being zero will leave an unexpandable execution image
which will claim about 100 kB if editor is loaded, about 80 kB
without. Data memory already reserved by ALLOCATE is not
included and should be added to the parameter for the amount of
the size of data area. For use of directory access words
OPEN-DIR, READ-DIR, CLOSE-DIR, an amount of 100 address units
should be reserved for each instance this will be made use of.

Caution! Parameters for an image exceeding available
RAM will leave an non-executable image!

.MEM       ( --)
Some values are displayed to reflect the current state of the
system, remaining sizes of memory areas, identifiers of
wordlists, tasks and heap memory areas.

TICKS      ( -- n)
A value is returned which is incremented once in a second.

TICKS>T&D  ( n -- ss mm hh dd mm yy)
Calculate the values for time and date from the value as given
by TICKS.

.DATE      ( --)
The current date is output to the console as given by the OS.

.TIME      ( --)
The current time is output to the console as given by the OS.

AVAILABLE  ( -- u)
Maximum size which may be reserved on the heap by ALLOCATE is
returned.

ERRORLEVEL ( -- a)


- Words available in Assembler wordlist -----------------------
  (if assembler loaded or not)

>CODES     ( -- a)
Variable, holds address of a table, in which the execution
tokens are kept for all assembler memory and dictionnary
accesses. As a default, assembler code is generated in code
area. This may be changed by providing a new table containing
execution tokens for the actions of C@, @, C!, !, HERE, ALLOT,
ALIGN, C, <"C-comma">, and , <"comma">.


- Words available in Editor wordlist --------------------------
  (if editor loaded or not)

B/BLK      ( -- 1024)
Return size of one block of a block file.

BLK-UM*    ( u -- d)
Multiply a given value with B/BLK, returning a double cell
product.

BLK/MOD    ( d -- mod div)
Divide a double cell number by B/BLK, returning modulo and
quotient.

-SKIP      ( a0 n char -- a0 n-)
-SCAN      ( a0 n char -- a0 n-)

WSCAN      ( a n1 n2 -- a+ n-)
In an array of cells represented by address of first cell and
count of cells, a value is scanned for which is given as top of
stack. If this value could be found, so the parameters of the
rest of the array is returned, starting at the address at which
the searched value is stored in and the numbers of cells
remaining, including the found position. Elsewise zero is
returned as top of stack and the first address behind the array.

?ESC       ( -- 1 /key:esc , -1 /cr , 0 , /space = wait)
Keyboard is scanned for a keypress. Enter key will return -1,
ESC key will return 1, else 0. If space key has been pressed, a
second press of space key is waited for. Other keypresses are
skipped.

TAB+       ( n --)
Cursor is positioned to next tab stop for a field width given as
parameter. If this field does not fit into the rest of the line,
a new line is started.

- Debugging ---------------------------------------------------

XDUMP      ( 'a n --)
Show a dump of code memory not addressable with data memory
words.

'SEE       ( cfa --)
Apply the function of SEE on the execution token given instead
of the name of a definition.

DEBUG      ( -- /"name")
Debugger is initialized to be called each time, the given <name>
will be executed next, if it is a secondary forth definition.
Exception handling and QUIT will disable the debugger. Debugger
is set to single step mode, so after each step, the Enter key
has to be pressed. Instead a line may be given to the
interpreter while debugging in single step mode. After execution
of this line, the prompt will be the forth prompt with the
leading string "debug: ". Next step will be executed if Enter is
pressed with an empty commandline. Debugging keys input is taken
from keyboard even if input source is a file. Some words used by
the debugger itself cannot be debugged, elsewise restrictions
for interpreter use while debugging are minimal. With shared
code of tasks, only the same instance of code will be debugged,
the debugger itself is working in.

'DEBUG     ( cfa --)
Apply the function of DEBUG on the execution token given instead
of the name of a definition.

FT         ( --)
Debugging mode is switched to "Fast Trace". This may be done at
any time after the debugger has been initialized. If Enter key
is pressed, so mode is switched to single step mode. If space
key is pressed, so output is halted until another pressing of
the space key.

NODEBUG    ( --)
While in single step debugging mode, debugger is switched off
and execution continuos without debugger.


- Internal Tasking --------------------------------------------

SELF       ( -- a)
Within a task, its own task identifier "tcb" is given.

PAUSE      ( --)
Essentially a nope, if tasker is switched off, elsewise a hook,
which enables next active task to continue execution until this
one by itself executes a PAUSE. Each system word performing I/O
ends with the action of PAUSE.

TASKER-ON  ( --)
Behaviour of PAUSE is switched to be a hook into next task in
the circular list of current active tasks.

TASKER-OFF ( --)
Behaviour of PAUSE is switched to be a NOPE. May be executed
within tasks instead of semaphores to protect access to open
files if used in conjunction with TASKER-ON - the interpreter is
switched off also this way, if it is not the current task from
where this is executed.

WAKE       ( tcb --)
A task is put into the circular list of current active tasks.

SLEEP      ( tcb --)
A task is taken out from the circular list of current active
tasks. If code of a task is placed in the memory area for which
a marker has been defined, so the action of SLEEP is performed
for this task, if that marker is executed and the task is
active. If a task is not an endless loop, so it will stop by
performing the action of SLEEP, and re-initialize itself after
finishing, for being restartable again by WAKE.

RUNS       ( tcb -- /"name")
To an existing and "sleeping" task, a new action is assigned to,
given by <name>.

TASK:      ( Execution:         -- tcb)
           ( Compilation: #R #S --  /"name")
Start of definition of a task <name>. Parameters are to be given
for sizes of task own return stack and parameter stack, in
address units, should be at least 64 for each of them. HERE and
PAD called from within a task will give addresses inside the
task. If scratch pad area shall be used inside the task, its
size should be taken into account of the size for the parameter
stack.


- Directory access --------------------------------------------

OPEN-DIR   ( a n method -- dir-id err#)
Given a string in data memory by its parameters, and the value
for a method (which will be ignored), an access will be tried to
be opened to a directory on the drive of which the name is
contained in the string. An internal identification value and 0
as top of stack will be returned if the operation succeeded,
elsewise a value different from 0 as top of stack and a
descardable value at next position on stack.

NEXT-DIR   ( dir-id -- dir-a err#)
Given a directory identification as returned by OPEN-DIR, the
next entry from the directory on the associated drive is read
and the address of a specfic storage area is returned together
with 0 if the operation succeeded, elsewise a non-zero value and
a discardable value at next position on stack.

CLOSE-DIR  ( dir-id -- err#)
Given a directory identification as returned by OPEN-DIR, all
other access to the directory on the associated drive by help of
this value is discarded. Temporarilly allocated heap storage area
is set free again.

>FATTR     ( dir-a -- a2)
In the specific storage area as given by READ-DIR the address of a
character field is calculated, from which a value may be read
(by "C@") which should reflect the attribute which the OS stored as
associated with the file of which the directory entry just has
been read.

>FTIME&DATE ( dir-a -- ss mm hh dd mm yy)
From the specific storage area as given by READ-DIR, six values
for time and date are calculated which are associated with the
file to which the just read directory entry belongs to. The
values are returned the same way as with forth facility word
TIME&DATE, with the values for seconds, minutes, hour, day,
month, year on stack, the value for the year of the date being
on top of the stack.

>FSIZE     ( dir-a -- a2)
In the specific storage area as given by READ-DIR, the address
of a double-cell field is calculated, in which the size of the
file may be read (by "2@") of which the directory entry just has
been read. After an OPEN-DIR but before a READ-DIR this will
give the amount of free memory available on the medium.

>FNAME     ( dir-a -- a2)
In the specific storage area as given by READ-DIR, the address
of a counted string is calculated, which holds the name of the
file of which the directory entry just has been read. A counted
string may be converted to the parameters of a string with
address and length by applying COUNT to the address of a counted
string as parameter. After an OPEN-DIR but before a READ-DIR
this will give the name the medium has been given when it was
formatted.

DIR        ( -- //"name")
The directory on a drive is shown of which <name> is given,
with names of files, sizes, and asterisks if they are
executables.

HEADER-READ     ( id -- dir-a err#)
QDOS Header information of an open file is read into an area
starting at "dir-a". Tools for queries from directory entries
may be applied; information for file-size is mapped as a
double-cell value.

HEADER-WRITE    ( id -- err#)
QDOS Header information of an open file is written back using
"dir-a" as obtained by HEADER-READ. If header information for
data allocation is to be changed, the adequate value should be
written as a single cell value into offset 6 of "dir-a" with
"!". If header information for file access is to be changed, the
adequate value (1 for an executable, 0 for a data file) should
be written into offset 5 of "dir-a" as a character value with
"C!".

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

***************************************************************
       ** Block File Editor **
***************************************************************

Before editing, first a block file has to be assigned to be the
default block file for the interpreter, using USE <name>.

If while editing more files have been opened, so the last one
edited will be the one which is assigned to be the default block
file after leaving the editor.

By envoking the editor, an "ID" is asked for, holding two
characters; this will be put into the top line of each changed
block while editing, if this line was not empty. The ID is put
together with current date in the form "ddmmmyyid" right
justified. If the ID query is skipped by only hitting the
enter-key, so no ID's will be written. If an ID is active, the
query is skipped.

Pushed lines and find-strings are preserved if the editor is
left and entered again. By entering the editor, state of the
debugger and values on the stack remain untouched except for the
case of read/write/open failures.

Cut&Paste between files may be done either by Push&Pop for
lines, or by setting markers as "from" and "up to" for blocks,
then switching to target file, then "copy marked blocks" and
"delete marked blocks". There should be no restriction on size
of copied areas other than dictated by the medium. Files will be
resized, cut (if TK2 is workable) or enlargened as necessary.

The functions for insertion of one block or deletion of current
block only work if dummy markers are set. Deletion of current
block will leave the last block of the file empty. Insertion
first will use an empty last block, before enlargening the file.

By using a block file with a size smaller than 1024 bytes, that
is less than one full block, this block probably is filled with
0's instead of with blanks - following the default behaviour of
the block cache system of the interpreter. These lines should be
deleted and the file should be flushed then, so the size is
reset to be 1024 bytes. Insertion of one block after that only
will work then, if this "block 0" is not left empty (that is: at
least a backslash as first character in first line may be
written). Block 0 never will be taken as input for the
interpreter, it is always a comment block. Block 1 for usual is
the block containing loading instructions for random access into
the file.

ED         ( --)
Start editing with the block of which the number is held in
variable SCR. By default this is 1, at start-up this is 0,
elsewise the number of the last block edited.

EDIT       ( blk --)
Start editing with the block of which the number is given as a
parameter.

ID-OFF     ( --)
Cancel a previously put-in ID.

ALL-FLUSH  ( --)
Flush all files open for the editor from within the interpreter.

ALL-CLOSE
Close all files open for the editor except the one last edited,
which is the default block file for the interpreter.

The following keys are assigned to:
(A=ALT, S=Shift, ^=CTRL)

**** Handle cursor ************
                   jump:
  left   right     column
A-left A-right     start/end of line
S-left S-right     word

up     down        row
S-up  S-down       top/bottom of screen

Tab   S-Tab        +/-  8 columns
Enter              next line, 1st column

**** Handle chars *************

^left  ^right      delete
^H                 delete
^Q                 toggle mode for insert/overwrite

**** Handle lines *************

^N insert
^Y delete
^Z delete
^O clear-EOL

^S split
^M join if next line fits

F3 push (buffer may hold 32 lines)
F4 push&copy
F5 pop if line fits

**** Handle screens ***********

 ^up    page back
 ^down  page ahead
A-up    page back
A-down  page ahead

S-A-up    1st screen of file
S-A-down  last screen of file

S-F5     "shadow" screen - toggle half of file-size back/ahead

^U       undo if updated
^D       delete current screen if marker set (ignore marker)
^T       insert one screen if marker set (ignore marker)

**** Find/Replace *************

F2  S-F2   input & find ahead / backwards
^L  ^K     find next / previous

( not implemented, but reserved keys: )
( ^R  ^E   find&replace next / previous)

**** Handle markers ***********

  F1  goto
A-F1  set
A-F2  reset

A-F3  copy marked blocks
A-F4  delete marked blocks

**** Handle files *************

 ^F3   open
 ^F4   close

S-F3   swap
S-F4   roll

 ^F    flush all open files
 ^B    make a backup

**** Leave editor *************

 ESC modified & flushed
^X   unmodified if updated

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